为了让向量检索加入链,可以使用RunnablePassthrough来实现
# 导入必要的库
from langchain_community.chat_models import ChatTongyi # 通义千问聊天模型
from langchain_core.vectorstores import InMemoryVectorStore # 内存向量存储
from langchain_community.embeddings import DashScopeEmbeddings # DashScope 嵌入模型
from langchain_core.prompts import ChatPromptTemplate # 聊天提示词模板
from langchain_core.output_parsers import StrOutputParser # 字符串输出解析器
from langchain_core.runnables import RunnablePassthrough # 可运行的通配符,用于传递输入
from langchain_core.documents import Document # 文档对象
# 初始化聊天模型
# 使用通义千问的 qwen3-max 模型
model = ChatTongyi(model="qwen3-max")
# 创建提示词模板,包含系统提示和用户提示
# 系统提示:要求模型以提供的参考资料为主,简洁专业地回答问题
# 用户提示:包含用户的具体问题
prompt = ChatPromptTemplate.from_messages([
("system", "以我提供的参考资料为主,简洁和专业的回答用户问题。参考资料:{context}。"),
("user", "用户提问:{input}"),
])
# 初始化内存向量存储,使用 DashScope 嵌入模型
# 嵌入模型用于将文本转换为向量表示,以便进行相似度搜索
vector_store = InMemoryVectorStore(embedding=DashScopeEmbeddings(model="text-embedding-v4"))
# 向向量库中添加文本数据
# 这里添加了三条与减肥相关的文本作为知识储备
vector_store.add_texts(["减肥就是要少吃多练","在减脂期间吃东西很重要,清淡少油控制卡路里摄入并运动起来","跑步是很好的运动哦"])
# 用户输入的问题
input_text = "如何减肥?"
# 定义一个函数,用于打印提示词内容
# 这样可以在链执行过程中看到完整的提示词
# 同时该函数会返回原始提示词,不影响链的执行
def print_prompt(prompt):
print(prompt.to_string())
print("="*20)
return prompt
# langchain中向量存储对象,有一个方法:as_retriever,可以返回一个Runnable接口的子类实例对象
# search_type="similarity" 表示使用相似度搜索
# search_kwargs={"k": 2} 表示返回最相似的2个结果
retriever = vector_store.as_retriever(search_type="similarity", search_kwargs={"k": 2})
# 定义一个函数,用于格式化检索到的文档
# 将文档列表转换为字符串格式,方便在提示词中使用
def format_func(docs: list[Document]):
if not docs:
return "无相关参考资料"
formatted_str = "["
for doc in docs:
formatted_str += f"{doc.page_content}"
formatted_str += "]"
return formatted_str
'''
retriever:
输入:用户的提问 str
输出:向量库的检索结果 list[Document]
prompt:
输入:用户的提问+向量库的检索结果 dict
输出:完整的提示词 PromptValue
'''
# 构建链式处理流程
# 1. 使用字典将输入分配给不同的键:
# - "input": 使用 RunnablePassthrough() 直接传递用户输入
# - "context": 使用 retriever 检索相关文档,然后通过 format_func 格式化
# 2. 将结果传递给 prompt 模板
# 3. 通过 print_prompt 函数打印完整提示词
# 4. 将提示词传递给模型生成回答
# 5. 使用 StrOutputParser 解析模型输出为字符串
chain = {"input": RunnablePassthrough(), "context": retriever | format_func} | prompt | print_prompt | model | StrOutputParser()
# 执行链并获取回答
answer = chain.invoke(input_text)
# 打印回答
print(answer)
System: 以我提供的参考资料为主,简洁和专业的回答用户问题。参考资料:[减肥就是要少吃多练在减脂期间吃东西很重要,清淡少油控制卡路里摄入并运动起来]。
Human: 用户提问:如何减肥?
====================
减肥的关键在于“少吃多练”:
- **饮食方面**:选择清淡、少油的食物,严格控制每日卡路里摄入;
- **运动方面**:坚持规律运动,增加热量消耗。
通过合理饮食与科学锻炼相结合,才能有效减脂并保持健康。