目录

AIGCOpenAI-集成-Langchain-操作实战使用详解

【AIGC】OpenAI 集成 Langchain 操作实战使用详解


一、前言

OpenAI作为人工智能领域的先锋,其提供的API为开发者打开了构建智能应用的大门。而作为LLM领域的佼佼者Langchain,随着RAG在众多的领域进行落地实践,Langchanin的热度也越来越高,然而,想要在实际项目中有效利用Langchanin提供的各种能力,了解如何使用Langchain进行集成是非常重要的。本文将详细介绍如何使用OpenAI集成Langchain,并使用Langchain的各种核心组件能力。

二、前置准备

在正式开始使用Langchain之前,你需要在本地准备基础的开发和运行环境,比如python环境、Langchain组件等,参考下面的操作步骤即可。

2.1 安装 Langchain必须的依赖

2.1.1 python环境

建议版本 3.10

https://i-blog.csdnimg.cn/direct/2ba1bc9956c3452cb499f9b011865b48.png

2.1.2 langchain openai 环境

使用下面的命令进行安装

pip install langchain openai

2.1.3 准备一个apikey

后面程序中调用API时候需要用到

2.1.4 langchain 核心组件

langchain 官网地址如下:

https://i-blog.csdnimg.cn/direct/3e9f34d93fec418cba109032cb6f7d8b.png

可以基于此文档查看langchain提供的各个组件以及API

三、Langchain 各组件使用

接下来将通过实际案例展示Langchain 各组件的详细使用

3.1 Chat models组件

文档地址: ,官方展示了可以对接LangChain的多种大模型,这里选择ChatOpenAi;

https://i-blog.csdnimg.cn/direct/2aed52695e774397b4cba1fdb9731e29.png

执行下面命令安装依赖组件

pip install -qU langchain-openai

3.1.1 Invocation 使用

参考官方提供案例

https://i-blog.csdnimg.cn/direct/0c466eae8760458ba64eebfd057beaf0.png

然后编写自己的代码,如下:


#langchain聊天的提示词模板
from langchain_core.prompts import ChatPromptTemplate

#langchain的openai的sdk
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    # 此处需要填入openai的key,可以直接填入,但建议最好可以配置到本地环境变量中
    api_key ='sk-...'
)

messages = [
    (
        "system",
        "You are a helpful assistant that translates English to Chinese. Translate the user sentence.",
    ),
    ("human", "I love programming."),
]
ai_msg = llm.invoke(messages)
print(ai_msg)

运行上面的代码,可以看到目标的英文被翻译成了中文

https://i-blog.csdnimg.cn/direct/95be93311a954bf5b558e3f72b95f9cb.png

或者使用下面的这种写法也是可以的

#langchain聊天的提示词模板
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import SystemMessage, HumanMessage

#langchain的openai的sdk
from langchain_openai import ChatOpenAI

#llm=ChatOpenAI()

model = ChatOpenAI(
    # 此处需要填入openai的key,可以直接填入,但建议最好可以配置到本地环境变量中
    api_key ='sk-...'
)

msg=[
    SystemMessage(content="请将下面的内容翻译成英语."), 
    HumanMessage(content="你好,请问你要去哪里")
]

res = model.invoke(msg)
print(res)

https://i-blog.csdnimg.cn/direct/bdef994309544803b222f7933751a63c.png

3.1.1.1 结果解析

如果上面的输出结果看起来不够直观,langchain的包里面还提供了内容解析的工具,只需要导入StrOutputParser包即可

#langchain聊天的提示词模板
from langchain_core.prompts import ChatPromptTemplate

#langchain的openai的sdk
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

#llm=ChatOpenAI()

llm = ChatOpenAI(
    # 此处需要填入openai的key,可以直接填入,但建议最好可以配置到本地环境变量中
    api_key ='sk-...'
)

prompt=ChatPromptTemplate.from_messages([
    ("system","您是世界级的技术专家."),
    ("user","{input}"),
])

#通过langcian的链式调用,生成一个提示词的chain
chain=prompt | llm

result=chain.invoke({"input":"帮我写一篇AI的技术文章,100字以内"})

print(result)

parser = StrOutputParser()
parser_str = parser.invoke(result)
print(parser_str)

再次运行上面的程序,此时得到的就是纯粹的内容了

https://i-blog.csdnimg.cn/direct/6599dff5c316493c94f80761810ad8df.png

3.2 提示词模板

3.2.1 什么是提示词模板

语言模型以文本作为输入,这个文本通常被称为提示词,在开发过程中,对于提示词来说不能直接硬编码,这样不利于提示词管理,而是通过提示词模板进行维护,类似于开发过程中遇到的短信模板,邮件模板等。

提示词模板是一种特殊的文本,它 可以为特定任务提供额外的上下文信息。 在LLM 应 用中,用户输入通常不直接被传递给模型本身, 而是被添加到一个更大的文本,即提示词模板中。提示词模板为当前的具体任务提供了额外的上下文信息,这能够更好地引导模型生成预期的输出。

一个提示词模板通常包含如下内容:

  • 发给大语言模型(LLM)指令;
  • 一组问答示例,以告诉AI以什么格式返回请求;
  • 发给大语言模型的问题;

3.2.2 创建提示词模板

在LangChain中,最简单的,可以使用PromptTemplate类创建简单的提示词模板。在提示词模板可以内嵌任意数量的模板参数,然后通过参数值格式化模板内容。

也可以使用MessagePromptTemplate来创建提示词模板。可以用一个或多MessagePromptTemplate创建一个ChatPromptTemplate

如下示例

from langchain.prompts.chat import(
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)

template =
(
    "You are a helpful assistant that translates [input_languagel to""(output_language}."
)

system_message_prompt=
    SystemMessagePromptTemplate.from_template(template)
    human_template ="(text}"human_message_prompt
    HumanMessagePromptTemplate.from_template(human_template)
    chat_prompt =ChatPromptTemplate.from_messages([
    system_message_prompt,
    human_message_prompt

chat_prompt.format_messages(input_language="English",output_language="French",text="I love programming."

上述代码首先定义了两个模板:

  • 一个是系统消息模板,描述了任务的上下文(翻译助手的角色和翻译任务);
  • 另一个是人类消息模板,其中的内容是用户的输入。然后,使用ChatPromptTemplate的from_messages方法将这两个模板结合起来,生成一个聊天提示词模板。
  • 当想要检查发送给模型的提示词是否确实与预期的提示词相符时,可以调用ChatPromptTemplate的format_messages方法,查看该提示词模板的最终呈现
msg=[
    SystemMessage(content="请将下面的内容翻译成英语."), 
    HumanMessage(content="你好,请问你要去哪里")
]

通过这种方式,不仅可以让聊天模型包装器生成预期的输出,对开发者来说,也不用担心是否符合提示词消息列表的数据格式,只需要提供具体的任务描述即可。

3.2.2.1 PromptTemplate 简单提示词模板

这是最简单的一种提示词模板,调用PromptTemplate的from_template方法,在模板内容中预留占位符作为后续的输入参数即可

#langchain聊天的提示词模板
from langchain_core.prompts import PromptTemplate

prompt_template = PromptTemplate.from_template("给我讲一个关于{topic}的历史故事")

result = prompt_template.format(topic="足球")

print(result)

运行一下,可以看到下面的效果,可以看到调用format方法的时候,最终“足球”就作为入参带入到模板中输出了

https://i-blog.csdnimg.cn/direct/6e1e97b81154476f870213afab3a73c3.png

3.2.2.2 ChatPromptTemplate 聊天提示词模板

如下是一段基本的提示词模板代码案例,设置了两个模板参数,调用的时候动态传入

#langchain聊天的提示词模板
from langchain_core.prompts import ChatPromptTemplate

#数组的每一个元素代表一个消息,每个消息元组,第一个参数代表消息角色,第二个参数代表消息内容
#消息角色:system代表系统消息,human代表人类消息,ai代表LLM返回的消息内容
#消息定义了2个模板参数name和user_input
chat_template = ChatPromptTemplate.from_messages(
    [
        ("system","你是一个人工智能助手,你的名字是{name}"),
        ("human","你好"),
        ("ai","我很好"),
        ("human","{user_input}")
    ]
)

#通过模板参数格式化模板内容
result = chat_template.format_messages(name="小明",user_input="你叫什么名")
print(result)

运行一下看到如下的效果输出

https://i-blog.csdnimg.cn/direct/308eec81db7640ff9618c5b0c1ebfa60.png

补充:

  • ChatPromptTemplate 用于聊天对话的场景中;
  • 后续接入大模型之后,就可以将参数拼接模板一起传给大模型,大模型就可以返回预期的结果了

ChatPromptTemplate 即聊天模型(Chat Model)提示词模板,聊天模型以聊天消息列表作为输入,这个聊天消息列表的消息内容也可以通过提示词模板进行管理,这些聊天消息与原始的字符串不同,因为每个消息都与“角色(Role)”相关联。

例如在OpenAI的Chat Completion API中,OpenAI的聊天模型,给不同聊天消息定义了三种角色类型,分别是:助手(Assistant),人类(Human),或系统(System)角色:

  • 助手(Assistant)消息指的是当前消息是AI回答的内容;
  • 人类(Human)消息值得是你发给AI的内容;
  • 系统(System)消息通常是用来给AI身份进行描述;

示例代码

参考下面的案例代码,结合代码中的注释进行理解,在提示词模板中,我们传入了两个变量,后续在调用的时候,只需要给这两个变量赋值即可

#langchain聊天的提示词模板
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_core.output_parsers import StrOutputParser

#langchain的openai的sdk
from langchain_openai import ChatOpenAI

model = ChatOpenAI(
    # 此处需要填入openai的key,可以直接填入,但建议最好可以配置到本地环境变量中
    api_key ='sk-...'
)

#定义模板
prompt_template=ChatPromptTemplate.from_messages([
    ("system","您是世界级的翻译专家,使用{language}语言翻译如下内容"),
    ("user","{input}"),
])

#内容输出解析器
output_parser=StrOutputParser()

#得到一个链
chain = prompt_template | model | output_parser

#输出结果
result = chain.invoke({'language':'中文','input':'hello world'})
print(result)

或者使用下面的这种写法

  • SystemMessage,对应着上面一种写法中的 ‘system’,由langchain自身API提供
  • HumanMessage,对应着上面一种写法中的 ‘user’,由langchain自身API提供
#langchain聊天的提示词模板
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.messages import SystemMessage, HumanMessage

#langchain的openai的sdk
from langchain_openai import ChatOpenAI

#llm=ChatOpenAI()

model = ChatOpenAI(
    # 此处需要填入openai的key,可以直接填入,但建议最好可以配置到本地环境变量中
    api_key ='sk-...'
)

msg=[
    SystemMessage(content="请将下面的内容翻译成英语."), 
    HumanMessage(content="你好,请问你要去哪里")
]

res = model.invoke(msg)
print(res)
3.2.2.3 MessagePlaceholer 聊天提示词模板

这个提示词模板负责在特定的位置添加消息列表,在上面的ChatPromptTemplate中,我们看到了如何格式化两条消息,每条消息都是一个字符串。但是如果我们希望用户传入一个消息列表,并将其插入到特定的位置该怎么办呢?这就需要使用到MessagePlaceholer 的方式。如下示例代码:

#langchain聊天的提示词模板
from langchain_core.prompts import ChatPromptTemplate,MessagesPlaceholder

from langchain_core.messages import SystemMessage, HumanMessage

prompt_template = ChatPromptTemplate.from_messages([
    ('system', 'You are a helpful assistant '),
    #这里可以传入一组消息
    MessagesPlaceholder('msgs')
])

result = prompt_template.invoke({"msgs":[HumanMessage(content="你好")]})
print(result)

https://i-blog.csdnimg.cn/direct/970f9573b4c34ef4a42819771f01900d.png

通过上面的运行结果不难看出,结果生成了2条消息,第一条是系统消息,第二条是我们传入的HumanMessage,如果我们传入了5条消息,那么一共会生成6条消息(系统消息加上传入的5条),这对于将一系列消息插入到特定的位置非常有用。

还有一种实现相同效果的的替代方法是,不直接使用MessagesPlaceholder,而是下面这种:

#langchain聊天的提示词模板
from langchain_core.prompts import ChatPromptTemplate,MessagesPlaceholder

from langchain_core.messages import SystemMessage, HumanMessage

prompt_template = ChatPromptTemplate.from_messages([
    ('system', 'You are a helpful assistant '),
    #这里可以传入一组消息
    # MessagesPlaceholder('msgs')
    ('placeholder','{msgs}')
])

result = prompt_template.invoke({"msgs":[HumanMessage(content="你好")]})
print(result)

效果是一样的

https://i-blog.csdnimg.cn/direct/920a412a6eeb4928accd1eea14f011de.png

3.2.2.4 少样本提示词模板

即Few-shot prompt template , 这种提示词模板中包含了少量的样本信息,这样做的目的是为了帮助模型更好的理解用户的意图,从而更好的回答问题或执行任务,少样本提示词模板是指使用一组少量的示例来指导模型处理新的输入。使用这些提示词可以用来训练模型,以便模型可以更好的理解或回答类似的问题。

Q:钢铁侠是谁?
A:钢铁侠是漫威中的一个英雄人物。

Q:什么是AI大模型?
A:...

告诉模型,Q是问题,A是答案,按照这种格式进行交互问答。后续大模型在回答问题的时候,就会参考你提供给它的示例,一定程度上可以避免大模型回答时产生的幻觉问题。

#langchain聊天的提示词模板
from langchain_core.prompts import ChatPromptTemplate,PromptTemplate
from langchain_core.prompts.few_shot import FewShotPromptTemplate

from langchain_core.messages import SystemMessage, HumanMessage

examples = [
    {
        "question":"什么是人工智能?",
        "answer":"人工智能(Artificial Intelligence)是指通过计算机模拟、扩展或扩展人的智能来构建智能系统的技术。"
    },
    {
        "question":"钢铁侠在漫威电影中一共出现了几次变身",
        "answer":"钢铁侠在漫威电影中一共出现了3次变身,分别是钢铁侠、浩克和美队。"
    },
    {
        "question":"詹姆斯一共打了多少赛季的篮球了?",
        "answer":"詹姆斯一共打了5个赛季的篮球,包括2003-2004赛季,2004-2005赛季,2005-2006赛季,2006-2007赛季,2007-2008赛季。"
    }
]

example_prompt = PromptTemplate(
    input_variables=["question","answer"],
    template="问题:{question}\n答案:{answer}"
)

#接收examples示例数组参数,通过example_prompt提示词模板批量渲染示例内容
#suffix和input_variables参数用于在提示词模板最后追加内容,input_variables用于定义suffix中包含的模板参数
prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    suffix="问题:{input}",
    input_variables=["input"]
)

print(prompt.format(input="詹姆斯在哪些赛季中出现过?"))

如下是一个使用openai调用的少样本案例代码

from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate
from langchain_openai import ChatOpenAI
import os

# 设置OpenAI API密钥

# 创建示例格式化器
example_prompt = PromptTemplate.from_template("Question: {question}\n{answer}")

# 准备示例集
examples = [
    {"question": "1+1等于几?", "answer": "答案是2"},
    {"question": "地球是什么形状?", "answer": "地球近似于一个球体"},
]

# 创建Few-Shot提示模板
prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    suffix="Question: {input}",
    input_variables=["input"],
)

# 创建OpenAI模型实例
llm = ChatOpenAI(
    # 此处需要填入openai的key,可以直接填入,但建议最好可以配置到本地环境变量中
    api_key ='sk-...'
)

# 生成提示并获取回答
user_question = "太阳系中最大的行星是哪个?"
full_prompt = prompt.invoke({"input": user_question}).to_string()
response = llm.invoke(full_prompt)

print(f"问题: {user_question}")
print(f"回答: {response}")

运行一下可以看到下面的结果

https://i-blog.csdnimg.cn/direct/a375a9932fae44c8a1c644fac89465fb.png

3.2.2.5 示例选择器

LangChain提供示例选择器来提高效率,避免一次性发送所有示例给模型,同时减少使用的Token数量。如果有大量示例,可能需要选择要包含在提示中的示例,示例选择器是负责执行此操作的类。

LangChain有几种不同类型的示例选择器

名称描述
SemanticSimilarityExampleSelector使用输入和示例之间的语义相似性来决定选择哪些示例。
MaxMarginalRelevanceExampleSelector使用输入和示例之间的最大边际相关性来决定选择哪些示例。
LengthBasedExampleSelector根据一定长度内可以容纳的数量来选择示例
NGramOverlapExampleSelector使用输入和示例之间的 ngram 重叠来决定选择哪些示例。

在下面的案例中,我们使用SemanticSimilarityExampleSelector类,该类根据输入的相似性选择小样本示例,它使用嵌入模型计算输入和小样本之间的相似性,然后使用向量数据库执行相似性搜索,获取输入相似的示例。

  • 这里涉及向量计算、向量数据库,在AI领域这两个主要用于数据库相似度搜索,例如,查询相似文章内容,相似图片、视频等

先安装下面的向量数据库

pip install chromadb

完整的代码如下

from langchain.prompts.example_selector import SemanticSimilarityExampleSelector
from langchain_community.vectorstores import Chroma

from langchain_openai import OpenAIEmbeddings

examples = [
    {
        "question":"什么是人工智能?",
        "answer":"人工智能(Artificial Intelligence)是指通过计算机模拟、扩展或扩展人的智能来构建智能系统的技术。"
    },
    {
        "question":"钢铁侠在漫威电影中一共出现了几次变身",
        "answer":"钢铁侠在漫威电影中一共出现了3次变身,分别是钢铁侠、浩克和美队。"
    },
    {
        "question":"詹姆斯一共打了多少赛季的篮球了?",
        "answer":"詹姆斯一共打了5个赛季的篮球,包括2003-2004赛季,2004-2005赛季,2005-2006赛季,2006-2007赛季,2007-2008赛季。"
    }
]

# 初始化示例选择器
example_selector = SemanticSimilarityExampleSelector.from_examples(
    #提供可选择的示例列表
    examples,
    #用于生成嵌入的嵌入类,该嵌入用于衡量语义的相似性
    OpenAIEmbeddings(api_key='sk-...'),
    #用于存储嵌入和执行相似度搜索的VectorStore类
    Chroma,
    #用于生成的示例数
    k=1
)

question = "詹姆斯在哪些赛季打过篮球?"

result_examples = example_selector.select_examples({"question":question})

for example in result_examples:
    print("\\n")
    for key, value in example.items():
        print(f"{key}: {value}")

运行一下上述代码,在输出的结果中可以看到参考了我们给定的示例样本,选择了最接近的问题的答案

https://i-blog.csdnimg.cn/direct/103fb81c20f24c47bf6a8449379ec023.png

3.3 memory组件

在多轮对话中,为了使大模型能够记住上下文对话,可以考虑使用这个memory组件,提前安装依赖包

pip install langchain_community

https://i-blog.csdnimg.cn/direct/6edcb821dde3447a8dc48e69e4f2a052.png

该模块中提供了ChatHistory,它允许聊天机器人记住过去的互动,并在后续的回答问题时考虑它们;

3.3.1 ChatMessageHistory 案例代码

参考如下代码


from langchain_community.chat_message_histories import ChatMessageHistory

#langchain聊天的提示词模板
from langchain_core.prompts import ChatPromptTemplate,MessagesPlaceholder
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_core.runnables import RunnableWithMessageHistory

#langchain的openai的sdk
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

#创建模型
model = ChatOpenAI(
    # 此处需要填入openai的key,可以直接填入,但建议最好可以配置到本地环境变量中
    api_key ='sk-...'
)

msg=[
    SystemMessage(content="请将下面的内容翻译成英语."), 
    HumanMessage(content="你好,请问你要去哪里")
]

parser=StrOutputParser()

#定义提示词模板
prompt_template = ChatPromptTemplate = ChatPromptTemplate.from_messages([
    ('system','你是一个乐于助人的助手,请用{language}尽你所能回答所有问题'),
    MessagesPlaceholder(variable_name="my_msg")

])

chain = prompt_template | model

#保存聊天的历史记录
store={}

#定义一个获取session_id的函数,返回一共消息的历史对象
def get_history(session_id: str):
    if session_id not in store:
        store[session_id] = ChatMessageHistory()
    return store[session_id]

do_msg = RunnableWithMessageHistory(
    chain,
    get_history,
   input_messages_key='my_msg' #每次聊天发送消息的key
)

#给当前会话添加一个session
config={'configurable':{'session_id':'xm113'}}

#第一轮对话
result_1 = do_msg.invoke(
    {
        "my_msg": [HumanMessage(content="你好,我是小明")],
        "language": "中文"
    },
    config=config
)

print(result_1.content)

#第二轮对话
result_2 = do_msg.invoke(
    {
        "my_msg": [HumanMessage(content="请问我的名字是什么")],
        "language": "中文"
    },
    config=config
)
print(result_2.content)

运行上面的代码,通过控制台的输出结果不难看出,大模型在回答我们的第二个问题的时候,由于使用了ChatMessageHistory,在第一次的对话中,记住了第一轮对话的内容,所以第二轮对话中可以正确的输出答案

https://i-blog.csdnimg.cn/direct/0010b4d64b854a03b33985763fccf96f.png

3.3.2 流式输出案例代码

流式输出是一种允许数据在生成的同时逐步传输的技术,而无需等待整个过程完成

流式输出技术使得数据可以实时地、逐步地传输,而不是等待所有数据生成完毕后再一次性传输。这种技术特别适用于处理大型语言模型(LLM)和聊天模型的输出,因为这些模型的运行时间通常较长,且输出数据量可能很大。通过流式输出,用户可以在数据生成的过程中就接收到部分结果,从而提高效率和用户体验。

基于上一个案例中的2轮对话,我们再加一轮对话,此时采用流式输出的方式,只需要调整下调用的api即可,如下:

#第三轮对话,此时返回的数据是流式的
for resp in do_msg.stream(
    {
        "my_msg": [HumanMessage(content="给我讲一个笑话")],
        "language": "中文"
    },
    config=config
): 
    print(resp.content)

运行上面的代码,观察输出效果,可以看到结果是一个一个字输出的

https://i-blog.csdnimg.cn/direct/bbac259e7a3949878739ae9a008a82c9.png

3.4 向量数据库与文档检索

向量数据库是实现文档检索的基础必要实现组件,类似与我们在学习es的时候,为了能从es中搜索出相似度最高的文档,es需要先将原始存入的数据进行分词之后再存储。

langchain构建的向量数据库与文档检索也是如此,不过文档存储是放在向量数据库中,即文档存储之前需要先进行向量化,而后才能进行搜索。

支持从向量数据库或其他数据源检索数据,以便与LLM(大语言模型)的工作流集成,这对于应用程序来说非常重要,这些应用程序需要获取数据以作为模型推理的一部分进行推理,就像检索增强生成(RAG)的情况类似。

3.4.1 安装向量数据库

向量数据库的可选组件有很多种,这里选用chroma,执行下面的命令安装

pip install langchain-chroma

https://i-blog.csdnimg.cn/direct/b0d21ed9ef46498cbad9cfb87206ec7d.png

3.4.2 代码操作示例

完整的操作步骤:

  • 初始化文档;
  • 文档存入向量数据库,进行文档向量化;
  • 使用检索器进行文档检索;

参考下面的完整代码


from langchain_community.chat_message_histories import ChatMessageHistory

from langchain_core.messages import SystemMessage, HumanMessage
from langchain_openai import ChatOpenAI

from langchain_core.documents import Document
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings

import os

os.environ["OPENAI_API_KEY"] = 'sk-...'


#提供测试数据,作为向量数据库数据的来源
documents = [
    Document(
        page_content="狗是人类的好朋友,以忠诚和友好而文明",
        metadata={"source": "哺乳动物手册"},
    ),
     Document(
        page_content="猫是比较独立的宠物,喜欢有自己独立的空间,但是可以为人类提供一定的陪伴和情绪价值",
        metadata={"source": "哺乳动物手册"},
    ),
     Document(
        page_content="兔子是一种乖巧而偏静的动物,既可以作为宠物,也可以作为家养动物",
        metadata={"source": "静态宠物手册"},
    ),
     Document(
        page_content="老虎是一个非常凶猛的动物,但是在非洲可以作为宠物,一般是捕食性动物",
        metadata={"source": "大型动物手册"},
    ),
     Document(
        page_content="长颈鹿是一种非常呆萌可爱的动物,一般在动物园才能看到",
        metadata={"source": "大型动物手册"}
    ),
]

#实例化向量空间
vector_store = Chroma.from_documents(documents, embedding = OpenAIEmbeddings())

#相似度查询,返回相似度分数,分数越低,相似度越高
result = vector_store.similarity_search_with_score("东北虎")
print(result)

运行上述的代码,通过控制台的结果输出不难发现,由于本次检索的关键字里面包含“虎“,在原始的文档中,与虎相关的文档有一个,所以最终检索的结果中,将包含老虎的那一条放在最前面,而且分数最低,这也就符合我们的预期

https://i-blog.csdnimg.cn/direct/00388c810b5046b0abb12bcb6d5df33c.png

当然,也可以使用检索器来做,即RunnableLambda这个对象,如下:

#实例化向量空间
vector_store = Chroma.from_documents(documents, embedding = OpenAIEmbeddings())

#相似度查询,返回相似度分数,分数越低,相似度越高
# result = vector_store.similarity_search_with_score("东北虎")
# print(result)

#检索器,k=1,选取相似度最高的第一个返回
retriever = RunnableLambda(vector_store.similarity_search_with_score).bind(k=1)

target_doc = retriever.batch(['华南虎','橘猫'])
print(target_doc)

再次运行上面的代码,此时返回了符合条件的两个文档

https://i-blog.csdnimg.cn/direct/9bb896eb8dc24bfd9508942a648bd235.png

3.4.3 组合大模型组件使用

事实上,在实际使用中可能会结合大模型一起使用,比如在下面的代码中,结合大模型与向量数据库一起使用,同时问题通过参数的方式传入,这样更为灵活一点


from langchain_community.chat_message_histories import ChatMessageHistory

from langchain_core.messages import SystemMessage, HumanMessage
from langchain_openai import ChatOpenAI

from langchain_core.documents import Document
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings

from langchain_core.runnables import RunnableLambda,RunnablePassthrough
from langchain_core.prompts import ChatPromptTemplate,MessagesPlaceholder

import os

os.environ["OPENAI_API_KEY"] = 'sk...'

#创建模型
model = ChatOpenAI(
    # 此处需要填入openai的key,可以直接填入,但建议最好可以配置到本地环境变量中
    api_key ='sk...'
)

msg=[
    SystemMessage(content="请将下面的内容翻译成英语."), 
    HumanMessage(content="你好,请问你要去哪里")
]

#提供测试数据,作为向量数据库数据的来源
documents = [
    Document(
        page_content="狗是人类的好朋友,以忠诚和友好而文明",
        metadata={"source": "哺乳动物手册"},
    ),
     Document(
        page_content="猫是比较独立的宠物,喜欢有自己独立的空间,但是可以为人类提供一定的陪伴和情绪价值",
        metadata={"source": "哺乳动物手册"},
    ),
     Document(
        page_content="兔子是一种乖巧而偏静的动物,既可以作为宠物,也可以作为家养动物",
        metadata={"source": "静态宠物手册"},
    ),
     Document(
        page_content="老虎是一个非常凶猛的动物,但是在非洲可以作为宠物,一般是捕食性动物",
        metadata={"source": "大型动物手册"},
    ),
     Document(
        page_content="长颈鹿是一种非常呆萌可爱的动物,一般在动物园才能看到",
        metadata={"source": "大型动物手册"}
    ),
]

#实例化向量空间
vector_store = Chroma.from_documents(documents, embedding = OpenAIEmbeddings())

#相似度查询,返回相似度分数,分数越低,相似度越高
# result = vector_store.similarity_search_with_score("东北虎")
# print(result)

#检索器,k=1,选取相似度最高的第一个返回
retriever = RunnableLambda(vector_store.similarity_search_with_score).bind(k=1)

#增加提示词模板
message="""
    使用提供的上下文回答这个问题:
    {question}
    上下文:
    {context}
"""

prompt_template = ChatPromptTemplate.from_messages([
    ('human',message)
])

#动态传递问题,允许用户的问题之后传递给prompt和model
chain = {'question':RunnablePassthrough(),'context':retriever} | prompt_template | model

resp = chain.invoke("请谈谈老虎")

print(resp)

从输出结果不难看出,最终的回答参考了本地向量数据库的答案

https://i-blog.csdnimg.cn/direct/d60fe63d64314872a1db3fc6c3c53e98.png

四、写在文末

本文通过案例详细介绍了OpenAI 集成 Langchain 的使用,并针对Langchain的核心组件以代码的方式进行了操作演示,希望对看到的同学有用哦,本篇到此结束,感谢观看。