引言
在构建智能问答系统时,结合语言模型和向量检索技术可以显著提升系统的性能和用户体验。LangChain 提供了强大的工具来实现这一目标,而 DeepSeek-R1 和智普AI向量模型则为问答系统提供了强大的语言处理和语义检索能力。本文将通过一个实际的代码示例,展示如何使用 LangChain 构建一个智能问答系统。
代码解析与技术要点
1. 环境与模型创建
在开始之前,我们需要设置环境变量并引入必要的库。以下是代码中的环境准备部分:
import os
from langchain_community.embeddings import ZhipuAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_core.documents import Document
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_openai import ChatOpenAI
os.environ['ZHIPUAI_API_KEY'] = 'your_zhipuai_api_key_here'
os.environ["OPENAI_API_KEY"] = "your_openai_api_key_here"
# 创建语言模型
model = ChatOpenAI(
model='deepseek-reasoner',
base_url="https://api.deepseek.com"
)
# 创建智普AI的向量模型
EMBEDDINGS = ZhipuAIEmbeddings(model="embedding-3")
技术要点:
-
os.environ['ZHIPUAI_API_KEY']
和os.environ["OPENAI_API_KEY"]
:分别设置智普AI和DeepSeek-R1的API密钥,这是调用外部模型的必要步骤。 -
langchain_openai.ChatOpenAI
和langchain_community.embeddings.ZhipuAIEmbeddings
:分别使用LangChain封装的DeepSeek-R1模型接口和智普AI的向量嵌入模型。
2. 准备测试数据
为了测试问答系统,我们需要准备一些文档数据。以下代码展示了如何创建文档对象并构建向量存储:
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": "爬行动物宠物文档"},
),
Document(
page_content="蜜袋鼯是可爱的飞行宠物,喜欢在空中滑翔。",
metadata={"source": "哺乳动物宠物文档"},
),
Document(
page_content="鸡尾鹦鹉是友好的鸟类,喜欢与人类互动。",
metadata={"source": "鸟类宠物文档"},
),
Document(
page_content="蝎子是神秘的宠物,需要干燥的环境。",
metadata={"source": "节肢动物宠物文档"},
),
]
vector_store = FAISS.from_documents(documents, embedding=EMBEDDINGS)
技术要点:
-
Document
:定义文档对象,包含文本内容和元数据。 -
FAISS.from_documents
:使用智普AI的向量嵌入模型将文档转换为向量,并存储到 FAISS 向量存储中。
3. 向量检索与相似度查询
LangChain 提供了强大的向量检索功能,可以快速找到与查询文本最相似的文档。以下代码展示了如何进行相似度查询和批量检索:
# 相似度的查询: 返回相似的分数,分数越低相似度越高
print(vector_store.similarity_search_with_score('猫'))
下面的检索结果可以看到又多条符合的文档;其中第一个评分值越低 0.8395272,表示返回的文档与查询结果越相似
[(Document(id=‘dae5d787-aaf1-44d3-8e21-825da0b5b39c’, metadata={‘source’: ‘哺乳动物宠物文档’}, page_content=‘龙猫是温顺的宠物,拥有柔软的皮毛。’), 0.8395272), (Document(id=‘464e796c-6b91-412f-9eeb-4dbe9185a510’, metadata={‘source’: ‘节肢动物宠物文档’}, page_content=‘蝎子是神秘的宠物,需要干燥的环境。’), 1.037286), (Document(id=‘f590cc8a-33b8-48a6-a076-a6ca765dffb4’, metadata={‘source’: ‘爬行动物宠物文档’}, page_content=‘蛇类宠物需要专业的饲养知识,适合有经验的爱好者。’), 1.0382364), (Document(id=‘d9593910-85bc-40c5-80a8-f80e0ad8d2dd’, metadata={‘source’: ‘哺乳动物宠物文档’}, page_content=‘蜜袋鼯是可爱的飞行宠物,喜欢在空中滑翔。’), 1.0946727)]
向量检索:
# 检索器: bind(k=1) 返回相似度最高的第一个
retriever = RunnableLambda(vector_store.similarity_search).bind(k=1)
# 批量检索
print(retriever.batch(['龙猫', '鱼']))
下面的检索结果可以看到返回了相似度最高的一个:
[[Document(id=‘dae5d787-aaf1-44d3-8e21-825da0b5b39c’, metadata={‘source’: ‘哺乳动物宠物文档’}, page_content=‘龙猫是温顺的宠物,拥有柔软的皮毛。’)], [Document(id=‘eafc7055-9654-4b08-9efd-1e13ef10b0da’, metadata={‘source’: ‘鱼类宠物文档’}, page_content=‘热带鱼色彩斑斓,需要精心维护的水族箱环境。’)]]
技术要点:
-
vector_store.similarity_search_with_score
:返回与查询文本最相似的文档及其相似度分数。 -
RunnableLambda
和bind(k=1)
:创建一个检索器,返回相似度最高的第一个文档。
4. 构建问答链
最后,我们将向量检索和语言模型结合,构建一个问答链。以下代码展示了如何实现这一功能:
message = """
使用提供的上下文仅回答这个问题:
{question}
上下文:
{context}
"""
prompt_temp = ChatPromptTemplate.from_messages([('human', message)])
chain = {'question': RunnablePassthrough(), 'context': retriever} | prompt_temp | model
resp = chain.invoke('请介绍一下鹦鹉?')
print(resp.content)
返回结果:
根据提供的上下文,鹦鹉中的鸡尾鹦鹉是一种友好的鸟类,它们喜欢与人类互动。这类鸟类通常适合作为宠物,因为它们表现出较强的社交性和与人建立联系的能力。
技术要点:
-
ChatPromptTemplate
:定义一个动态的 Prompt 模板,根据检索到的上下文和用户问题生成完整的 Prompt。 -
RunnablePassthrough
:允许将用户问题直接传递给 Prompt 和模型。 -
chain
:将检索器、Prompt 和模型结合,形成一个完整的问答链。
总结
通过 LangChain 和 DeepSeek-R1,结合智普AI的向量嵌入模型,我们可以轻松构建一个智能问答系统。这种组合不仅提高了开发效率,还为开发者提供了强大的语言处理和语义检索能力。希望这篇博客能帮助你更好地理解和使用这些技术。