【langchain】AI应用开发框架
介绍langchain(1.2版本)的基础使用入门,agent部分下一篇文章见~
背景
LangChain 由 Harrison Chase 创建于2022年10月,它是围绕LLMs(大语言模型)建立的一个框架。
简单来说:它是一个Python的第三方库
LangChain自身并不开发LLMs,它的核心理念是为各种LLMs实现通用的接口,把LLMs相关的组件“链接”在一起,简化LLMs应用的开发难度,方便开发者快速地开发复杂的LLMs应用。
简介

环境部署
安装相关包
pip install langchain langchain-community langchain-ollama langchain-chroma dashscope chromadb bs4 jq

具体演示
现在市面上的模型多如牛毛,各种各样的模型不断出现,LangChain模型组件提供了与各种模型的集成,并为所有模型提供一个精简的统一接口。
LangChain目前支持三种类型的模型:LLMs(大语言模型)、Chat Models(聊天模型)、Embeddings Models(嵌入模型)。
1.LLMs:是技术范畴的统称,指基于大参数量、海量文本训练的 Transformer 架构模型,核心能力是理解和生成自然语言,主要服务于文本生成场景 。
2.聊天模型:是应用范畴的细分,是专为对话场景优化的 LLMs,核心能力是模拟人类对话的轮次交互,主要服务于聊天场景 。
3.文本嵌入模型: 文本嵌入模型接收文本作为输入, 得到文本的向量. LangChain支持的三类模型,它们的使用场景不同,输入和输出不同,开发者需要根据项目需要选择相应。
我们这次以阿里云通义千问系列进行演示,它主要来自于:langchain_community包
1.demo快速验证
from langchain_community.llms.tongyi import Tongyi
### 实例化模型
llm = Tongyi(model='qwen-max')
### 模型推理
res = llm.invoke("帮我讲个笑话吧")
print(res)
如果要访问本地Ollama的模型,简单更改一下代码。 通过langchain_ollama包导入OllamaLLM类即可(请确保Ollama已经启动并提前下载好要使用的模型)。
2.流式输出
如果需要流式输出结果,需要将模型的invoke方法改为stream方法即可。
1.invoke方法:一次型返回完整结果
2.stream方法:逐段返回结果,流式输出

3.聊天类型
聊天消息包含下面几种类型,使用时需要按照约定传入合适的值:
1.AIMessage: 就是 AI 输出的消息,可以是针对问题的回答. (OpenAI库中的assistant角色)
2.HumanMessage :人类消息就是用户信息,由人给出的信息发送给LLMs的提示信息,比如“实现一个快速排序方法”. (OpenAI库中的user角色)
3.SystemMessage: 可以用于指定模型具体所处的环境和背景,如角色扮演等。你可以在这里给出具体的指示,比如“作为一个代码专家”,或者“返回json格式”. (OpenAI库中的system角色)。
from langchain_ollama import ChatOllama
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
# 得到模型对象, qwen3-max就是聊天模型
model = ChatOllama(model="qwen3:4b")
# 准备消息列表
messages = [
SystemMessage(content="你是一个边塞诗人。"),
HumanMessage(content="写一首唐诗"),
AIMessage(content="锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦。"),
HumanMessage(content="按照你上一个回复的格式,在写一首唐诗。")
]
# 调用stream流式执行
res = model.stream(input=messages)
# for循环迭代打印输出,通过.content来获取到内容
for chunk in res:
print(chunk.content, end="", flush=True)
4.Embeddings Models(文本嵌入模型)
Embeddings Models嵌入模型的特点:将字符串作为输入,返回一个浮点数的列表(向量)。 在NLP中,Embedding的作用就是将数据进行文本向量化。
from langchain_community.embeddings import DashScopeEmbeddings
# 创建模型对象 不传model默认用的是 text-embeddings-v1
model = DashScopeEmbeddings()
# 不用invoke stream
# embed_query、embed_documents
print(model.embed_query("我喜欢你"))
print(model.embed_documents(["我喜欢你", "我稀饭你", "晚上吃啥"]))
5.通用prompt(zero-shot)
提示词优化在模型应用中非常重要,LangChain提供了PromptTemplate类,用来协助优化提示词。 PromptTemplate表示提示词模板,可以构建一个自定义的基础提示词模板,支持变量的注入,最终生成所需的提示词。
from langchain_core.prompts import PromptTemplate
from langchain_community.llms.tongyi import Tongyi
# zero-shot
prompt_template = PromptTemplate.from_template(
"我的邻居姓{lastname}, 刚生了{gender}, 你帮我起个名字,简单回答。"
)
model = Tongyi(model="qwen-max")
# 调用.format方法注入信息即可
# prompt_text = prompt_template.format(lastname="张", gender="女儿")
#
# model = Tongyi(model="qwen-max")
# res = model.invoke(input=prompt_text)
# print(res)
chain = prompt_template | model
res = chain.invoke(input={"lastname": "张", "gender": "女儿"})
print(res)
6.FewShotPromptTemplate(少样本实例)
FewShotPromptTemplate参数:
examples:示例数据,list,内套字典
example_prompt:示例数据的提示词模板
prefix:组装提示词,示例数据前内容
suffix:组装提示词,示例数据后内容
input_variables:列表,注入的变量列表
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate
from langchain_community.llms.tongyi import Tongyi
# 示例的模板
example_template = PromptTemplate.from_template("单词:{word}, 反义词:{antonym}")
# 示例的动态数据注入 要求是list内部套字典
examples_data = [
{"word": "大", "antonym": "小"},
{"word": "上", "antonym": "下"},
]
few_shot_template = FewShotPromptTemplate(
example_prompt=example_template, # 示例数据的模板
examples=examples_data, # 示例的数据(用来注入动态数据的),list内套字典
prefix="告知我单词的反义词,我提供如下的示例:", # 示例之前的提示词
suffix="基于前面的示例告知我,{input_word}的反义词是?", # 示例之后的提示词
input_variables=['input_word'] # 声明在前缀或后缀中所需要注入的变量名
)
prompt_text = few_shot_template.invoke(input={"input_word": "左"}).to_string()
print(prompt_text)
model = Tongyi(model="qwen-max")
print(model.invoke(input=prompt_text))
7.ChatPromptTemplate
1.PromptTemplate:通用提示词模板,支持动态注入信息。
2.FewShotPromptTemplate:支持基于模板注入任意数量的示例信息。 3.ChatPromptTemplate:支持注入任意数量的历史会话信息。
通过from_messages方法,从列表中获取多轮次会话作为聊天的基础模板
PS: 前面PromptTemplate类用的from_template仅能接入一条消息,而from_messages可以接入一个list的消息
历史会话信息并不是静态的(固定的),而是随着对话的进行不停地积攒,即动态的。 所以,历史会话信息需要支持动态注入。
MessagePlaceholder作为占位 提供history作为占位的key 基于invoke动态注入历史会话记录 必须是invoke,format无法注入
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_community.chat_models.tongyi import ChatTongyi
chat_prompt_template = ChatPromptTemplate.from_messages(
[
("system", "你是一个边塞诗人,可以作诗。"),
MessagesPlaceholder("history"),
("human", "请再来一首唐诗"),
]
)
history_data = [
("human", "你来写一个唐诗"),
("ai", "床前明月光,疑是地上霜,举头望明月,低头思故乡"),
("human", "好诗再来一个"),
("ai", "锄禾日当午,汗滴禾下锄,谁知盘中餐,粒粒皆辛苦"),
]
# StringPromptValue to_string()
prompt_text = chat_prompt_template.invoke({"history": history_data}).to_string()
model = ChatTongyi(model="qwen3-max")
res = model.invoke(prompt_text)
print(res.content, type(res))
8.chain
「将组件串联,上一个组件的输出作为下一个组件的输入」是 LangChain 链(尤其是 | 管道链)的核心工作原理,这也是链式调用的核心价值:实现数据的自动化流转与组件的协同工作,如下。
chain = prompt_template | model
核心前提:即Runnable子类对象才能入链(以及Callable、Mapping接口子类对象也可加入(后续了解用的不多))。 我们目前所学习到的组件,均是Runnable接口的子类,如下类的继承关系:

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_community.chat_models.tongyi import ChatTongyi
chat_prompt_template = ChatPromptTemplate.from_messages(
[
("system", "你是一个边塞诗人,可以作诗。"),
MessagesPlaceholder("history"),
("human", "请再来一首唐诗"),
]
)
history_data = [
("human", "你来写一个唐诗"),
("ai", "床前明月光,疑是地上霜,举头望明月,低头思故乡"),
("human", "好诗再来一个"),
("ai", "锄禾日当午,汗滴禾下锄,谁知盘中餐,粒粒皆辛苦"),
]
model = ChatTongyi(model="qwen3-max")
# 组成链,要求每一个组件都是Runnable接口的子类
chain = chat_prompt_template | model
# 通过链去调用invoke或stream
# res = chain.invoke({"history": history_data})
# print(res.content)
# 通过stream流式输出
for chunk in chain.stream({"history": history_data}):
print(chunk.content, end="", flush=True)
LangChain中链是一种将各个组件串联在一起,按顺序执行,前一个组件的输出作为下一个组件的输入。
1.可以通过 “|” 符号来让各个组件形成链
2.成链的各个组件,需是Runnable接口的子类
3.形成的链是RunnableSerializable对象(Runnabl接口子类)
4.可通过链调用invoke或stream触发整个链条的执行
9.StrOutputParser字符串输出解析器
StrOutputParser是LangChain内置的简单字符串解析器。 可以将AIMessage类型转换为基础字符串 可以加入chain作为组件存在(Runnable接口子类)
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_community.chat_models.tongyi import ChatTongyi
parser = StrOutputParser()
model = ChatTongyi(model="qwen3-max")
prompt = PromptTemplate.from_template(
"我邻居姓:{lastname},刚生了{gender},请起名,仅告知我名字无需其它内容。"
)
chain = prompt | model | parser | model | parser
res: str = chain.invoke({"lastname": "张", "gender": "女儿"})
print(res)
print(type(res))
10.JsonOutPutParser
同理转换json格式
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_community.chat_models.tongyi import ChatTongyi
from langchain_core.prompts import PromptTemplate
# 创建所需的解析器
str_parser = StrOutputParser()
json_parser = JsonOutputParser()
# 模型创建
model = ChatTongyi(model="qwen3-max")
# 第一个提示词模板
first_prompt = PromptTemplate.from_template(
"我邻居姓:{lastname},刚生了{gender},请帮忙起名字,"
"并封装为JSON格式返回给我。要求key是name,value就是你起的名字,请严格遵守格式要求。"
)
# 第二个提示词模板
second_prompt = PromptTemplate.from_template(
"姓名:{name},请帮我解析含义。"
)
# 构建链 (AIMessage("{name: 张若曦}")
chain = first_prompt | model | json_parser | second_prompt | model | str_parser
for chunk in chain.stream({"lastname": "张", "gender": "女儿"}):
print(chunk, end="", flush=True)
11.RunnableLambda 自定义函数
如果像要在链中加入自定义函数,可以选择:
1.将函数封装入RunnableLambda类对象,其是Runnable接口实例,可以直接入链
2.直接将函数入链,函数会自动转换为RunnableLambda对象
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_community.chat_models.tongyi import ChatTongyi
model = ChatTongyi(model="qwen3-max")
str_parser = StrOutputParser()
first_prompt = PromptTemplate.from_template(
"我邻居姓:{lastname},刚生了{gender},请帮忙起名字,仅生成一个名字,并告知我名字,不要额外信息。"
)
second_prompt = PromptTemplate.from_template(
"姓名{name},请帮我解析含义。"
)
# 函数的入参:AIMessage -> dict ({"name": "xxx"})
# my_func = RunnableLambda(lambda ai_msg: {"name": ai_msg.content})
chain = first_prompt | model | (lambda ai_msg: {"name": ai_msg.content}) | second_prompt | model | str_parser
for chunk in chain.stream({"lastname": "曹", "gender": "女孩"}):
print(chunk, end="", flush=True)
12.Memory 临时会话记忆
如果想要封装历史记录,除了自行维护历史消息外,也可以借助LangChain内置的历史记录附加功能。 LangChain提供了History功能,帮助模型在有历史记忆的情况下回答。
1.基于RunnableWithMessageHistory在原有链的基础上创建带有历史记录功能的新链(新Runnable实例)
2.基于InMemoryChatMessageHistory为历史记录提供内存存储(临时用)
from langchain_community.chat_models.tongyi import ChatTongyi
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.chat_history import InMemoryChatMessageHistory
model = ChatTongyi(model="qwen3-max")
# prompt = PromptTemplate.from_template(
# "你需要根据会话历史回应用户问题。对话历史:{chat_history},用户提问:{input},请回答"
# )
prompt = ChatPromptTemplate.from_messages(
[
("system", "你需要根据会话历史回应用户问题。对话历史:"),
MessagesPlaceholder("chat_history"),
("human", "请回答如下问题:{input}")
]
)
str_parser = StrOutputParser()
def print_prompt(full_prompt):
print("="*20, full_prompt.to_string(), "="*20)
return full_prompt
base_chain = prompt | print_prompt | model | str_parser
store = {} # key就是session,value就是InMemoryChatMessageHistory类对象
# 实现通过会话id获取InMemoryChatMessageHistory类对象
def get_history(session_id):
if session_id not in store:
store[session_id] = InMemoryChatMessageHistory()
return store[session_id]
# 创建一个新的链,对原有链增强功能:自动附加历史消息
conversation_chain = RunnableWithMessageHistory(
base_chain, # 被增强的原有chain
get_history, # 通过会话id获取InMemoryChatMessageHistory类对象
input_messages_key="input", # 表示用户输入在模板中的占位符
history_messages_key="chat_history" # 表示用户输入在模板中的占位符
)
if __name__ == '__main__':
# 固定格式,添加LangChain的配置,为当前程序配置所属的session_id
session_config = {
"configurable": {
"session_id": "user_001"
}
}
# res = conversation_chain.invoke({"input": "小明有2个猫"}, session_config)
# print("第1次执行:", res)
#
# res = conversation_chain.invoke({"input": "小刚有1只狗"}, session_config)
# print("第2次执行:", res)
res = conversation_chain.invoke({"input": "总共有几个宠物"}, session_config)
print("第3次执行:", res)
RunnableWithMessageHistory是LangChain内Runnable接口的实现,主要用于:
创建一个带有历史记忆功能的Runnable实例(链)
1.它在创建的时候需要提供一个BaseChatMessageHistory的具体实现(用来存储历史消息) 2.InMemoryChatMessageHistory可以实现在内存中存储历史
额外的,如果想要在invoke或stream执行链的同时,将提示词print出来,可以在链中加入自定义函数实现。 注意:函数的输入应原封不动返回出去,避免破坏原有业务,仅在return之前,print所需信息即可。
13.Memory 长期会话记忆
使用InMemoryChatMessageHistory仅可以在内存中临时存储会话记忆,一旦程序退出,则记忆丢失。 InMemoryChatMessageHistory 类继承自 BaseChatMessageHistory
FileChatMessageHistory类实现,核心思路:
基于文件存储会话记录,以session_id为文件名,不同session_id有不同文件存储消息
继承BaseChatMessageHistory实现如下3个方法:
1.add_messages:同步模式,添加消息
2.messages:同步模式,获取消息
3.clear:同步模式,清除消息
import os, json
from typing import Sequence
from langchain_community.chat_models import ChatTongyi
from langchain_core.messages import message_to_dict, messages_from_dict, BaseMessage
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnableWithMessageHistory
# message_to_dict:单个消息对象(BaseMessage类实例) -> 字典
# messages_from_dict:[字典、字典...] -> [消息、消息...]
# AIMessage、HumanMessage、SystemMessage 都是BaseMessage的子类
class FileChatMessageHistory(BaseChatMessageHistory):
def __init__(self, session_id, storage_path):
self.session_id = session_id # 会话id
self.storage_path = storage_path # 不同会话id的存储文件,所在的文件夹路径
# 完整的文件路径
self.file_path = os.path.join(self.storage_path, self.session_id)
# 确保文件夹是存在的
os.makedirs(os.path.dirname(self.file_path), exist_ok=True)
def add_messages(self, messages: Sequence[BaseMessage]) -> None:
# Sequence序列 类似list、tuple
all_messages = list(self.messages) # 已有的消息列表
all_messages.extend(messages) # 新的和已有的融合成一个list
# 将数据同步写入到本地文件中
# 类对象写入文件 -> 一堆二进制
# 为了方便,可以将BaseMessage消息转为字典(借助json模块以json字符串写入文件)
# 官方message_to_dict:单个消息对象(BaseMessage类实例) -> 字典
# new_messages = []
# for message in all_messages:
# d = message_to_dict(message)
# new_messages.append(d)
new_messages = [message_to_dict(message) for message in all_messages]
# 将数据写入文件
with open(self.file_path, "w", encoding="utf-8") as f:
json.dump(new_messages, f)
@property # @property装饰器将messages方法变成成员属性用
def messages(self) -> list[BaseMessage]:
# 当前文件内: list[字典]
try:
with open(self.file_path, "r", encoding="utf-8") as f:
messages_data = json.load(f) # 返回值就是:list[字典]
return messages_from_dict(messages_data)
except FileNotFoundError:
return []
def clear(self) -> None:
with open(self.file_path, "w", encoding="utf-8") as f:
json.dump([], f)
model = ChatTongyi(model="qwen3-max")
# prompt = PromptTemplate.from_template(
# "你需要根据会话历史回应用户问题。对话历史:{chat_history},用户提问:{input},请回答"
# )
prompt = ChatPromptTemplate.from_messages(
[
("system", "你需要根据会话历史回应用户问题。对话历史:"),
MessagesPlaceholder("chat_history"),
("human", "请回答如下问题:{input}")
]
)
str_parser = StrOutputParser()
def print_prompt(full_prompt):
print("="*20, full_prompt.to_string(), "="*20)
return full_prompt
base_chain = prompt | print_prompt | model | str_parser
def get_history(session_id):
return FileChatMessageHistory(session_id, "./chat_history")
# 创建一个新的链,对原有链增强功能:自动附加历史消息
conversation_chain = RunnableWithMessageHistory(
base_chain, # 被增强的原有chain
get_history, # 通过会话id获取InMemoryChatMessageHistory类对象
input_messages_key="input", # 表示用户输入在模板中的占位符
history_messages_key="chat_history" # 表示用户输入在模板中的占位符
)
if __name__ == '__main__':
# 固定格式,添加LangChain的配置,为当前程序配置所属的session_id
session_config = {
"configurable": {
"session_id": "user_001"
}
}
# res = conversation_chain.invoke({"input": "小明有2个猫"}, session_config)
# print("第1次执行:", res)
#
# res = conversation_chain.invoke({"input": "小刚有1只狗"}, session_config)
# print("第2次执行:", res)
res = conversation_chain.invoke({"input": "总共有几个宠物"}, session_config)
print("第3次执行:", res)
14.RecursiveCharacterTextSplitter
RecursiveCharacterTextSplitter,递归字符文本分割器,主要用于按自然段落分割大文档。 是LangChain官方推荐的默认字符分割器。 它在保持上下文完整性和控制片段大小之间实现了良好平衡,开箱即用效果佳。
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
# pip install langchain_text_splitters
loader = TextLoader("./data/Python基础语法.txt", encoding="utf-8")
docs = loader.load() # [Document]
splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 分段的最大字符数
chunk_overlap=50, # 分段之间允许重叠字符数
# 文本自然段落分隔的依据符号
separators=["\n\n", "\n", "。", "!", "?", ".", "!", "?", " ", ""],
length_function=len, # 统计字符的依据函数
)
split_docs = splitter.split_documents(docs)
print(len(split_docs))
for doc in split_docs:
print("="*20)
print(doc)
print("="*20)
TextLoader是一个简单的加载器,可以加载文本文件内容,返回仅有一个Document对象的list。 RecursiveCharacterTextSplitter递归字符文本分割器,是LangChain官方推荐的默认分割器。 基于文本的自然段落分割大文档为小文档 可以指定小文档的最大字符数、重叠字符数 可以手动指定段落划分的依据(符号)以及字符数量统计函数
15.Vector stores 向量存储

内存存储:
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_community.document_loaders import CSVLoader
vector_store = InMemoryVectorStore(
embedding=DashScopeEmbeddings()
)
loader = CSVLoader(
file_path="./data/info.csv",
encoding="utf-8",
source_column="source", # 指定本条数据的来源是哪里
)
documents = loader.load()
# id1 id2 id3 id4 ...
# 向量存储的 新增、删除、检索
vector_store.add_documents(
documents=documents, # 被添加的文档,类型:list[Document]
ids=["id"+str(i) for i in range(1, len(documents)+1)] # 给添加的文档提供id(字符串) list[str]
)
# 删除 传入[id, id...]
vector_store.delete(["id1", "id2"])
# 检索 返回类型list[Document]
result = vector_store.similarity_search(
"瑞达法",
3 # 检索的结果要几个
)
print(result)
外部持久化存储:
from langchain_chroma import Chroma
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_community.document_loaders import CSVLoader
# Chroma 向量数据库(轻量级的)
# 确保 langchain-chroma chromadb 这两个库安装了的,没有的话请pip install
vector_store = Chroma(
collection_name="test", # 当前向量存储起个名字,类似数据库的表名称
embedding_function=DashScopeEmbeddings(), # 嵌入模型
persist_directory="./chroma_db" # 指定数据存放的文件夹
)
# loader = CSVLoader(
# file_path="./data/info.csv",
# encoding="utf-8",
# source_column="source", # 指定本条数据的来源是哪里
# )
#
# documents = loader.load()
# # id1 id2 id3 id4 ...
# # 向量存储的 新增、删除、检索
# vector_store.add_documents(
# documents=documents, # 被添加的文档,类型:list[Document]
# ids=["id"+str(i) for i in range(1, len(documents)+1)] # 给添加的文档提供id(字符串) list[str]
# )
#
# # 删除 传入[id, id...]
# vector_store.delete(["id1", "id2"])
# 检索 返回类型list[Document]
result = vector_store.similarity_search(
"Python是不是简单易学呀",
3, # 检索的结果要几个
filter={"source": "黑马程序员"}
)
print(result)
LangChain内提供向量存储功能,可以基于: InMemoryVectorStore,完成内存向量存储 Chroma,外部数据库向量存储 向量存储类均提供3个通用API接口:
add_document,添加文档到向量存储
delete,从向量存储中删除文档
similarity_search:相似度搜索
"""
提示词:用户的提问 + 向量库中检索到的参考资料
"""
from langchain_community.chat_models import ChatTongyi
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
def print_prompt(prompt):
print(prompt.to_string())
print("=" * 20)
return prompt
model = ChatTongyi(model="qwen3-max")
prompt = ChatPromptTemplate.from_messages(
[
("system", "以我提供的已知参考资料为主,简洁和专业的回答用户问题。参考资料:{context}。"),
("user", "用户提问:{input}")
]
)
vector_store = InMemoryVectorStore(embedding=DashScopeEmbeddings(model="text-embedding-v4"))
# 准备一下资料(向量库的数据)
# add_texts 传入一个 list[str]
vector_store.add_texts(
["减肥就是要少吃多练", "在减脂期间吃东西很重要,清淡少油控制卡路里摄入并运动起来", "跑步是很好的运动哦"])
input_text = "怎么减肥?"
# 检索向量库
result = vector_store.similarity_search(input_text, 2)
reference_text = "["
for doc in result:
reference_text += doc.page_content
reference_text += "]"
chain = prompt | print_prompt | model | StrOutputParser()
res = chain.invoke({"input": input_text, "context": reference_text})
print(res)
16.RunnablePassthrough的使用
让向量检索入链
"""
提示词:用户的提问 + 向量库中检索到的参考资料
"""
from langchain_community.chat_models import ChatTongyi
from langchain_core.documents import Document
from langchain_core.runnables import RunnablePassthrough
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
def print_prompt(prompt):
print(prompt.to_string())
print("=" * 20)
return prompt
model = ChatTongyi(model="qwen3-max")
prompt = ChatPromptTemplate.from_messages(
[
("system", "以我提供的已知参考资料为主,简洁和专业的回答用户问题。参考资料:{context}。"),
("user", "用户提问:{input}")
]
)
vector_store = InMemoryVectorStore(embedding=DashScopeEmbeddings(model="text-embedding-v4"))
# 准备一下资料(向量库的数据)
# add_texts 传入一个 list[str]
vector_store.add_texts(
["减肥就是要少吃多练", "在减脂期间吃东西很重要,清淡少油控制卡路里摄入并运动起来", "跑步是很好的运动哦"])
input_text = "怎么减肥?"
# langchain中向量存储对象,有一个方法:as_retriever,可以返回一个Runnable接口的子类实例对象
retriever = vector_store.as_retriever(search_kwargs={"k": 2})
def format_func(docs: list[Document]):
if not docs:
return "无相关参考资料"
formatted_str = "["
for doc in docs:
formatted_str += doc.page_content
formatted_str += "]"
return formatted_str
# chain
chain = (
{"input": RunnablePassthrough(), "context": retriever | format_func} | prompt | print_prompt | model | StrOutputParser()
)
res = chain.invoke(input_text)
print(res)
"""
retriever:
- 输入:用户的提问 str
- 输出:向量库的检索结果 list[Document]
prompt:
- 输入:用户的提问 + 向量库的检索结果 dict
- 输出:完整的提示词 PromptValue
"""
下篇文章我们介绍agent相关内容~
更多推荐



所有评论(0)