大模型开发框架LangChain

一、简述

1 什么是LangChain

LangChain由 Harrison Chase 创建于2022年10月,它是围绕LLMs(大语言模型)建立的一个框架,它的核心理念是为各种LLMs实现通用的接口,把LLMs相关的组件"链接"在一起,简化LLMs应用的开发难度,方便开发者快速地开发复杂的LLMs应用。

LangChain 最初是于 2022 年 10 月开源的一个项目,在 GitHub 上获得大量关注之后迅速转变为一家初创公司。2017 年 Harrison Chase 还在哈佛上大学,如今已是硅谷的一家热门初创公司的 CEO,这对他来说是一次重大而迅速的跃迁。Insider 独家报道,人工智能初创公司 LangChain 在种子轮一周后,再次获得红杉领投的 2000 万至 2500 万美元融资,估值达到 2 亿美元。

LangChain官网python.langchain.com/docs/introd...

LangChain官网中文版www.langchain.com.cn/

LangChain 简化了 LLM 应用程序生命周期的每个阶段:

  • 开发:使用 LangChain 的开源组件和第三方集成构建应用程序。使用 LangGraph 构建具有一流流式和人机交互支持的状态智能体。
  • 生产化:使用 LangSmith 检查、监控和评估应用程序,方便持续优化和部署。
  • 部署:使用 LangGraph平台 将应用程序转变为可用于生产的 API 和助手。

2 主要组件

  • Models:模型,各种类型的模型和模型集成,比如GPT-4
  • Prompts:提示,包括提示管理、提示优化和提示序列化
  • Chains:链,一系列对各种组件的调用
  • Memory:记忆,用来保存和模型交互时的上下文状态
  • Indexes:索引,用来结构化文档,以便和模型交互
  • Agents:代理,决定模型采取哪些行动,执行并且观察流程,直到完成为止

3 LangChain核心包

  • langchain-core:聊天模型和其他组件的基础抽象。

  • 集成包(例如 langchain-openai、langchain-anthropic 等):重要的集成被拆分为轻量级的独立包,由 LangChain 团队和集成方共同维护。

  • langchain:包含链(chains)、智能体(agents)和检索策略,这些构成了应用的认知架构。

  • langchain-community:由社区维护的第三方集成。

  • langgraph:一个编排框架,用于将 LangChain 组件组合成可用于生产的应用,支持持久化、流式处理及其他关键特性。

4 环境准备

本课程以LangChain+Qwen进行学习,需要提前安装

pip install openai

pip install langchain

pip install modelscope

借助阿里云-百炼平台(需要申请API Key 以及Secret Key):

bailian.console.aliyun.com/#/home

二、Models

现在市面上的模型多如牛毛,各种各样的模型不断出现,LangChain模型组件提供了与各种模型的集成,并为所有模型提供一个精简的统一接口。

LangChain目前支持三种类型的模型:LLMs、Chat Models(聊天模型)、Embeddings Models(嵌入模型)。

  • LLMs:大语言模型接收文本字符作为输入,返回的也是文本字符。
  • 聊天模型:基于LLMs, 不同的是它接收聊天消息(一种特定格式的数据)作为输入,返回的也是聊天消息。
  • 文本嵌入模型:文本嵌入模型接收文本作为输入, 返回的是浮点数列表。

LangChain支持的三类模型,它们的使用场景不同,输入和输出不同,开发者需要根据项目需要选择相应的模型。

1 LLMs

LLMs(大语言模型)使用场景最多,常用大模型的下载库:

huggingface.co/models

modelscope.cn/models

下面Qwen为例进行讲解。


模型调用有2种方式:

  • 通过ChatOpenAI进行调用
python 复制代码
from langchain_openai import ChatOpenAI
import  os

# 实例化模型
model = ChatOpenAI(
    base_url=os.environ.get('base_url','https://dashscope.aliyuncs.com/compatible-mode/v1'),
    model='qwen-plus',
    openai_api_key=os.environ.get('api_key','sk-XXXXXX'),
    max_tokens=1000,
    temperature=0
)

# 获取问答结果
result = model.invoke("帮我讲个笑话吧")
print(result.content)
python 复制代码
# from langchain_community.llms import Ollama # Langchain 0.x版本使用
from langchain_ollama import OllamaLLM

# 实例化模型
# model = Ollama(model="qwen2.5:7b") # Langchain 0.x版本使用
model = OllamaLLM(model="qwen2.5:7b")

# 获取问答结果
result = model.invoke("请给我讲个笑话吧")
print(result)

2 Chat Models

聊天模型,聊天消息包含下面几种类型,使用时需要按照约定传入合适的值:

  • AIMessage: 就是 AI 输出的消息,可以是针对问题的回答.

  • HumanMessage: 人类消息就是用户信息,由人给出的信息发送给LLMs的提示信息,比如"实现一个快速排序方法".

  • SystemMessage: 可以用于指定模型具体所处的环境和背景,如角色扮演等。你可以在这里给出具体的指示,比如"作为一个代码专家",或者"返回json格式".

  • ChatMessage: Chat 消息可以接受任意角色的参数,但是在大多数时间,我们应该使用上面的三种类型.

LangChain支持大量的chat 模型,可以通过官网查询:

python.langchain.com/docs/integr...

也可以通过langchain源码查看

  • SystemMessage+HumanMessage+AIMessage
python 复制代码
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage
# from langchain_community.chat_models import ChatOllama # Langchain 0.x版本使用
from langchain_ollama import ChatOllama

# 实例化模型
model = ChatOllama(model="qwen2.5:7b")

# 定义提示词
messages = [
        SystemMessage(content="现在你是一个著名的诗人"),
        HumanMessage(content="给我写一首唐诗")]

# 获取问答结果
result = model.invoke(messages)
# print(result)
print(result.content)

3 Embeddings Models

Embeddings Models(嵌入模型)特点:将字符串作为输入,返回一个浮动数的列表。在NLP中,Embedding的作用就是将数据进行文本向量化。

python.langchain.com/docs/integr...


不同的Embedding模型对多语言支持和文本类型有不同的特点:

  • 多语言支持
    • text-embedding-ada-002:支持多种语言,但对中文等亚洲语言的支持相对较弱
    • bge-large-zh:对中文有很好的支持
    • multilingual-e5-large:对多语言都有较好的支持
    • mxbai-embed-large:
  • 文本类型适用性
    • 代码文本:建议使用专门的代码Embedding模型,如 CodeBERT
    • 通用文本:可以使用text-embedding-ada-002bge-large-zh
    • 专业领域文本:建议使用该领域的专门模型

可以参考MTEB(大规模文本嵌入基准)排行榜以获取最新模型效果:huggingface.co/spaces/mteb...

接下来以一个文本嵌入模型的例子进行说明:

python 复制代码
# from langchain_community.embeddings import OllamaEmbeddings # Langchain 0.x版本使用
from langchain_ollama import OllamaEmbeddings

# 初始化Ollama嵌入模型,使用mxbai-embed-large模型,温度设置为0
model = OllamaEmbeddings(model="mxbai-embed-large", temperature=0)

# 对单个查询文本进行嵌入编码
res1 = model.embed_query('这是第一个测试文档')

print(f'result1->{res1}')
print(f'result1的长度->{len(res1)}')

# 对多个文档进行批量嵌入编码
res2 = model.embed_documents(['这是第一个测试文档', '这是第二个测试文档'])
print(res2)

运行结果:

三、Prompts

1 通用prompt

Prompt是指当用户输入信息给模型时加入的提示,这个提示的形式可以是zero-shot或者few-shot等方式,目的是让模型理解更为复杂的业务场景以便更好的解决问题。

提示模板:如果你有了一个起作用的提示,你可能想把它作为一个模板用于解决其他问题,LangChain就提供了PromptTemplates组件,它可以帮助你更方便的构建提示。

  • zero-shot提示方式
python 复制代码
# from langchain import PromptTemplate # Langchain 0.x版本使用
from langchain_core.prompts import PromptTemplate
# from langchain_community.llms import Ollama  # Langchain 0.x版本使用
from langchain_ollama import OllamaLLM

# model = Ollama(model="qwen2.5:7b") # Langchain 0.x版本使用
model = OllamaLLM(model="qwen2.5:7b")
# 定义模板
template = "我的邻居姓{lastname},他生了个儿子,给他儿子起个名字"

prompt = PromptTemplate(
    input_variables=["lastname"],
    template=template)

prompt_text = prompt.format(lastname="王")
print(prompt_text)
# result: 我的邻居姓王,他生了个儿子,给他儿子起个名字

result = model.invoke(prompt_text)
print(result)

运行结果:

  • few-shot提示方式
python 复制代码
# from langchain import PromptTemplate, FewShotPromptTemplate # Langchain 0.x版本使用
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate
from langchain_ollama import OllamaLLM

model = OllamaLLM(model="qwen2.5:7b")

examples = [
    {"word": "开心", "antonym": "难过"},
    {"word": "高", "antonym": "矮"}]

example_template = """
单词: {word}
反义词: {antonym}\\n
"""

example_prompt = PromptTemplate(
    input_variables=["word", "antonym"],
    template=example_template,
)

few_shot_prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    prefix="给出每个单词的反义词",
    suffix="单词: {input}\\n反义词:",
    input_variables=["input"],
    example_separator="\\n",
)

prompt_text = few_shot_prompt.format(input="粗")

print(model.invoke(prompt_text))
# 细

2 ChatPrompts

适合交互式对话应用,如聊天机器人、智能客服等,这些应用需要处理用户和LLM之间的多轮对话。

ChatPromptTemplate

SystemMessagePromptTemplate

HumanMessagePromptTemplate

history=("system","......"),('human',"......"),("ai","......")

  • 直接提问

提示模板就是把一些常见的提示整理成模板,用户只需要修改模板中特定的词语,就能快速准确地告诉模型自己的需求。我们看个例子:

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import OllamaLLM

# 实例化模型
model = OllamaLLM(model="qwen2.5:7b")

# 定义提示词模版
template_str = "帮我讲个关于{name}笑话吧"
prompt_template = ChatPromptTemplate.from_template(template_str)
prompt = prompt_template.format_messages(name="气球")
print(f'prompt-->{prompt}')

# 调用模型
result = model.invoke(prompt)
print(f'result-->{result}')
  • zero-shot提示方式
python 复制代码
from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_core.messages import SystemMessage
from langchain_ollama import OllamaLLM

# 实例化模型
model = OllamaLLM(model="qwen2.5:7b")

# 系统信息
system_prompt = SystemMessage("你是取名专家。")
# 用户信息模版
human_str = "我的邻居姓{lastname},他生了个儿子,给他儿子起个名字。"
human_template = HumanMessagePromptTemplate.from_template(human_str)
# 组装
chat_template = ChatPromptTemplate.from_messages([system_prompt, human_template])
# 生成最终的提示词
prompt = chat_template.format_messages(lastname="王")
print(f'prompt-->{prompt}')

# 调用模型
result = model.invoke(prompt)  # 返回结果出了content外,还有元数据信息
print(f'result-->{result}')

运行结果:

  • few-shot提示方式
python 复制代码
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_ollama import OllamaLLM

# 实例化模型
model = OllamaLLM(model="qwen2.5:7b")

# 创建 prompt 模版
prompt_template = ChatPromptTemplate.from_messages(
      [
         ("system", "给出每个单词的反义词"),
         MessagesPlaceholder("history"),
         ("human", "{question}")
      ]
)
# 创建 few-shot prompt
# history = [
#     HumanMessage(content="开心"),
#     AIMessage(content="难过"),
#     HumanMessage(content="高"),
#     AIMessage(content="矮")
# ]
history = [("human", "开心"), ("ai", "难过"),("human", "高"), ("ai", "矮")]
prompt = prompt_template.format_messages(history=history, question="富有")
print(f"prompt-->{prompt}")

# 调用模型
result = model.invoke(prompt)
print(f'result-->{result}')

运行结果:

四、Chains

在LangChain中,Chains描述了将LLM与其他组件结合起来完成一个应用程序的过程。 针对上一小节的提示模版例子,zero-shot里面,我们可以用链来连接提示模版组件和模型,进而可以实现代码的更改,主要使用LCEL方法。

LCEL(Lang Chain Expression Language) 是一种声明式的方法,用于轻松组合链条。

LCEL的基本语法规则是使用|符号将不同的组件连接起来,形成一个链式结构。|符号类似于Unix的管道操作符,它将一个组件的输出作为下一个组件的输入,从而实现数据的传递和处理。

上一个组件的输出作为下一个组件的输入,输出和输入的类型必须保持一致,否则不能连接。

python 复制代码
from langchain import PromptTemplate
from langchain_core.prompts import PromptTemplate
from langchain_ollama import OllamaLLM

# 定义模板
template = "我的邻居姓{lastname},他生了个儿子,给他儿子起个名字"

prompt = PromptTemplate(
    input_variables=["lastname"],
    template=template)

# 实例化模型
llm = OllamaLLM(model="qwen2.5:7b")

chain = prompt | llm
# 执行链
print(chain.invoke("王"))

如果你想将第一个模型输出的结果,直接作为第二个模型的输入,直接使用管道符, 代码如下:

python 复制代码
from langchain_core.prompts import PromptTemplate
from langchain_ollama import OllamaLLM

# 创建第一条链
template = "我的邻居姓{lastname},他生了个儿子,给他儿子起个名字"

first_prompt = PromptTemplate(
    input_variables=["lastname"],
    template=template,)

# 实例化模型
llm = OllamaLLM(model="qwen2.5:7b")

first_chain = first_prompt | llm

# 创建第二条链
second_prompt = PromptTemplate(
    input_variables=["child_name"],
    template="邻居的儿子名字叫{child_name},给他起一个小名")

second_chain = second_prompt | llm

# 链接两条链
overall_chain = first_chain | second_chain

print(overall_chain)
print('*'*80)
# 执行链,只需要传入第一个参数
catchphrase = overall_chain.invoke("王")
print(catchphrase)

运行结果:

五、output_parsers

LLM 的输出是自然语言文本,但在应用开发中,我们经常需要将这些文本转换为结构化的数据格式,如列表、字典或对象。LangChain 输出解析器负责获取 LLM 的输出并将其转换为更合适的格式。

部分解析器如下:

解析器名称 核心功能 输出的 Python 类型 工业级应用场景
StrOutputParser 默认解析器。将 LLM 的输出直接解析为字符串。 str 只需要原始回答时(如问答任务、对话场景)
CommaSeparatedListParser 将 LLM 输出的、用逗号分隔的文本解析为列表。 liststr 列表/枚举型输出
JsonOutputParser 极其常用。将 LLM 输出的 JSON 字符串解析为 Python 字典。 dict 结构化 JSON 输出
PydanticOutputParser 极其常用。将 LLM 输出解析为预先定义的 Pydantic 对象,提供类型安全和数据验证。 自定义的 pydantic.BaseModel 对象 输出需要严格结构化(JSON-like)数据时
DatetimeOutputParser 从文本中智能地解析出日期和时间信息。 datetime.datetime 需要时间格式时

1 字符串解析器

StrOutputParser,最简单的解析器,用于提取模型返回的原始文本:

python 复制代码
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import OllamaLLM

# 实例化模型
model = OllamaLLM(model="qwen2.5:7b")

# 创建简单链
prompt = ChatPromptTemplate.from_template("解释{topic}是什么?回答控制20字以内")
chain1 = prompt | model
result1 = chain1.invoke({"topic": "ai"})
print(f"result1-->{result1}")

# 添加字符串解析器
parser = StrOutputParser()
chain2 = prompt | model | parser
result2 = chain2.invoke({"topic": "ai"})
print(f"result2-->{result2}")

2 列表解析器

CommaSeparatedListOutputParser,将逗号分隔的文本转换为Python列表:

python 复制代码
from langchain_core.output_parsers import CommaSeparatedListOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import OllamaLLM

# 实例化模型
model = OllamaLLM(model="qwen2.5:7b")

# 创建列表解析器
parser = CommaSeparatedListOutputParser()

# 创建带格式说明的提示模板
format_instructions = parser.get_format_instructions()
prompt = ChatPromptTemplate.from_template(
    "用中文列出{topic}的五个最重要特点。\n{format_instructions}"
)

# 组合组件
chain = prompt | model | parser

# 调用链
result = chain.invoke({
    "topic": "大模型",
    "format_instructions": format_instructions
})
print(result)

3 JSON解析器

JsonOutputParser,将JSON格式文本转换为Python字典或列表:

python 复制代码
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import OllamaLLM

# 实例化模型
model = OllamaLLM(model="qwen2.5:7b")

# 创建JSON解析器
json_parser = JsonOutputParser()

# 创建带格式说明的提示模板
json_format_instructions = json_parser.get_format_instructions()
json_prompt = ChatPromptTemplate.from_template(
    "生成一个包含{person}基本信息的JSON。应包括姓名、职业、年龄和技能列表, 不要包含任何注释或额外说明。\n{format_instructions}"
)

# 组合组件
json_chain = json_prompt | model | json_parser

# 调用链
result = json_chain.invoke({
    "person": "雷军",
    "format_instructions": json_format_instructions
})

print(result)

运行结果:

4 Pydantic解析器

PydanticOutputParser,使用Pydantic模型定义输出结构:

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
from typing import List
from langchain_ollama import OllamaLLM

# 实例化模型
model = OllamaLLM(model="qwen2.5:7b")

# 定义Pydantic模型
class Movie(BaseModel):
    title: str = Field(description="电影标题")
    director: str = Field(description="导演姓名")
    year: int = Field(description="上映年份")
    genre: List[str] = Field(description="电影类型")
    rating: float = Field(description="评分(1-10)")


# 创建Pydantic解析器
pydantic_parser = PydanticOutputParser(pydantic_object=Movie)

# 创建带格式说明的提示模板
format_instructions = pydantic_parser.get_format_instructions()
pydantic_prompt = ChatPromptTemplate.from_template(
    "生成一部{genre}电影的信息。\n{format_instructions}"
)

# 组合组件
pydantic_chain = pydantic_prompt | model | pydantic_parser

# 调用链
movie_data = pydantic_chain.invoke({
    "genre": "科幻",
    "format_instructions": format_instructions
})
print(movie_data)

运行结果:

5 自定义解析器

创建自定义输出解析器

python 复制代码
from langchain_core.output_parsers import BaseOutputParser
from typing import Dict, Any
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import OllamaLLM

# 实例化模型
model = OllamaLLM(model="qwen2.5:7b")

class CustomKeyValueParser(BaseOutputParser[Dict[str, Any]]):
    """解析形如'key: value'的文本"""
    def parse(self, text: str) -> Dict[str, Any]:
        """从文本中解析键值对"""
        result = {}
        lines = text.strip().split('\n')

        for line in lines:
            if ':' in line:
                key, value = line.split(':', 1)
                result[key.strip()] = value.strip()

        return result

    def get_format_instructions(self) -> str:
        """提供格式指导给模型"""
        return """请以'键: 值'的格式返回信息,每行一个键值对。
                例如:
                名称: 爱因斯坦
                职业: 物理学家
                贡献: 相对论"""


# 使用自定义解析器
custom_parser = CustomKeyValueParser()
custom_prompt = ChatPromptTemplate.from_template(
    "提供关于{person}的基本信息。\n{format_instructions}"
)

# 组合组件
custom_chain = custom_prompt | model | custom_parser

# 调用模型
result = custom_chain.invoke({
    "person": "屠呦呦",
    "format_instructions": custom_parser.get_format_instructions()
})
print(result)

运行结果:

六、Memory

大模型本身不具备上下文的概念,它并不保存上次交互的内容,ChatGPT之所以能够和人正常沟通对话,因为它进行了一层封装,将历史记录回传给了模型。

因此 LangChain 也提供了Memory组件, Memory分为两种类型: 短期记忆和长期记忆 。短期记忆一般指单一会话时传递数据,长期记忆则是处理多个会话时获取和更新信息。

  • 使用 ChatMessageHistory 手动添加上下文
python 复制代码
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.messages import messages_to_dict, messages_from_dict
import json

# 1.创建一个ChatMessageHistory对象,用来存储对话信息
history = ChatMessageHistory()
# 添加用户消息
history.add_user_message("在吗?")
# 添加大模型消息
history.add_ai_message("在")
# 打印所有消息
print(f'history.messages-->{history.messages}')

# 2.可以将history.messages中的信息保存到字典中,然后保存到数据库或者文件中,方便后续读取
# 2.1 messages_to_dict()方法将history.messages中的信息转换成字典
dicts = messages_to_dict(history.messages)
print(f'dicts-->{dicts}')
# 2.2 这里将dicts保存到文件中
with open('history.json', 'w', encoding='utf-8') as f:
    f.write(json.dumps(dicts, indent=2, ensure_ascii=False))

# 3.从文件中读取出字典,然后将字典转换成消息
# 3.1 读取文件
messages = json.load(open('history.json', 'r', encoding='utf-8'))
# 3.2 然后将字典转换成消息
chat_messages = messages_from_dict(messages)
print(f'chat_messages-->{chat_messages}')

运行结果:

LangChain v1.0 版本对 Memory(记忆) 组件进行了深度优化与工程化重构,使其不仅支持多轮对话上下文管理,更成为构建生产级智能体(Agent)不可或缺的核心能力之一。在 LangChain 从"实验性框架"迈向"企业级平台"的关键转型中,Memory 模块被赋予了更清晰的职责边界、更灵活的策略机制以及更强的可扩展性,从而支撑复杂任务场景下的长期记忆、状态追踪与个性化交互。

1 短期记忆(Short-term Memory)

短期记忆的本质是线程级状态管理]。在 LangGraph 中:

短期记忆 = Agent 状态(State) + 检查点持久化(Checkpointer) + 线程标识(thread_id)。

(1)状态(State)

通常是一个包含 messages 字段的字典或 Pydantic 模型(如 MessagesState 或自定义 CustomState),用于存储当前会话的所有消息、中间变量、工具调用结果等。

(2)检查点器(Checkpointer)

负责将状态序列化并持久化到内存、SQLite、PostgreSQL 等后端。每次状态变更(如新增一条消息)都会触发一次检查点保存。

(3)会话ID(thread_id)

作为会话的唯一标识符,确保不同用户或不同对话之间的状态完全隔离。即使多个用户并发交互,也不会发生记忆混淆。

python 复制代码
from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver
from langchain.messages import HumanMessage
from langchain_ollama import OllamaLLM
import time

# 初始化大模型,这里使用的是 Qwen 的聊天模型
model = OllamaLLM(model="qwen2.5:7b")

# 创建内存保存器 (Checkpointer)
# 这是 LangGraph 的核心概念之一,用于在对话过程中保存和恢复状态(记忆)
checkpointer = InMemorySaver()

# 定义 Agent 的配置
# "thread_id" (线程ID) 非常关键:它相当于对话的 ID,用于区分不同的会话记忆
# 使用时间戳作为 ID,确保每次运行脚本时的线程 ID 不同(但在同一次运行中复用)
timestamp = time.time()
config = {
    "configurable": {"thread_id": f"{int(timestamp)}"}
}

# 创建 Agent 实例
# model: 指定使用的底层大模型
# tools: 工具列表,这里为空,表示 Agent 只能进行对话,不能调用外部工具(如搜索、计算器等)
# checkpointer: 传入上面的内存保存器,赋予 Agent 记忆能力
# system_prompt: 设定 Agent 的角色和行为模式
agent = create_agent(
    model=model,
    tools=[],
    checkpointer=checkpointer,
    system_prompt="你是一个翻译官,擅长中英互译。"
)

# 第一轮对话输入
input_1 = {
    "messages": [HumanMessage("你好,我叫小呆。")]
}

# 调用 Agent (Response A)
# 使用 config,这意味着这次对话会记录在 thread_id 对应的内存中
# Agent 会记住 "我叫小呆" 这个信息
response_a = agent.invoke(
    input=input_1,
    config=config
)

# 第二轮对话输入(测试是否记得之前的信息)
input_2 = {
    "messages": [HumanMessage("你好,我叫什么?")]
}

# 定义一个新的配置 (config_2),使用完全不同的 thread_id
# 这代表开启了一个全新的、独立的对话会话
config_2 = {
    "configurable": {"thread_id": f"{int(time.time())}"}  # 这里生成了一个新的时间戳 ID
}

# 调用 Agent (Response B)
# 使用新的 config_2,Agent 看不到 config_1 中的历史记录
# 因此,Agent 应该不知道用户叫 "小呆",因为它处于一个新的 "线程" 中
response_b = agent.invoke(
    input=input_2,
    config=config_2
)

# 调用 Agent (Response C)
# 再次使用最初的 config
# 这会恢复到第一个会话的记忆中
# Agent 应该能回想起用户叫 "小呆",因为它共享同一个 thread_id
response_c = agent.invoke(
    input=input_2,
    config=config
)

# 输出结果进行对比
print("Response A (第一次对话):")
print(response_a)

print("\nResponse B (新线程,无记忆):")
print(response_b)

print("\nResponse C (回到原线程,有记忆):")
print(response_c)

代码运行逻辑:

  • checkpointer (记忆核心):这是 LangGraph 区别于传统简单 API 调用的关键。它允许 Agent 在多次 invoke 调用之间保存状态。
  • thread_id (记忆索引) :你可以把 thread_id 想象成数据库中的主键。
    • Response A:向 ID 为 100 的记录里写入了名字。
    • Response B:向 ID 为 200 的新记录提问,因为 200 是空的,所以 Agent 不知道名字。
    • Response C:又回到 ID 为 100 的记录提问,Agent 读取了历史记录,所以知道名字。
  • System Prompt:虽然输入是在对话,但因为设定了 "你是一个翻译官",Agent 可能会试图在回答的同时进行翻译,或者在回复格式上符合翻译官的身份。

2 长期记忆

对于需要长期运行和可靠记忆的应用,推荐使用数据库进行持久化。详见后面阶段LangGraph部分。

七、Indexes

Indexes组件的目的是让LangChain具备处理文档处理的能力,包括:文档加载、检索等。注意,这里的文档不局限于txt、pdf等文本类内容,还涵盖email、区块链、视频等内容。

Indexes组件主要包含类型:

  • 文档加载器
  • 文本分割器
  • VectorStores
  • 检索器

1 文档加载器

python.langchain.com/v0.2/docs/i...

文档加载器主要基于Unstructured 包,Unstructured 是一个python包,可以把各种类型的文件转换成文本。文档加载器使用起来很简单,只需要引入相应的loader工具。

LangChain支持的文档加载器 (部分):

示例代码:

需要安装的包:

pip install unstructured

pip install langchain-unstructured

python 复制代码
from langchain_unstructured import UnstructuredLoader

# 创建 UnstructuredLoader 对象
loader = UnstructuredLoader('./data/衣服属性.txt', encoding='utf8')
docs = loader.load()
print(f'docs-->{docs}')
print(f'len-->{len(docs)}')
print(f'第一行数据-->{docs[0].page_content}')
print('*' * 100)

from langchain_community.document_loaders import TextLoader

# 创建 TextLoader 对象
loader = TextLoader('./data/衣服属性.txt', encoding='utf8')
docs = loader.load()
print(f'docs-->{docs}')
print(f'len-->{len(docs)}')
print('第一行数据-->{}'.format(docs[0].page_content.split('\n')[0]))

运行结果:

2 文档分割器

由于模型对输入的字符长度有限制,我们在碰到很长的文本时,需要把文本分割成多个小的文本片段。

文本分割最简单的方式是按照字符长度进行分割,但是这会带来很多问题,比如说如果文本是一段代码,一个函数被分割到两段之后就成了没有意义的字符,所以整体的原则是把语义相关的文本片段放在一起。

LangChain中最基本的文本分割器是CharacterTextSplitter ,它按照指定的分隔符(默认"\n\n")进行分割,并且考虑文本片段的最大长度。我们看个例子:

python 复制代码
from langchain_core.documents import Document
from langchain_text_splitters import CharacterTextSplitter

# 创建分词器 separator参数指的是分割的分隔符,chunk_size指的是分割出来的每个块的大小,chunk_overlap指的是每个块之间重叠的大小
text_splitter = CharacterTextSplitter(separator=" ", chunk_size=5, chunk_overlap=1)

# 一句话分割
result1 = text_splitter.split_text("a b c d e f")
print(f'result1--->{result1}')

# 多句话分割
result2 = text_splitter.create_documents(["a b c d e f", "e f g h"])
print(f'result2--->{result2}')

# 多句话分割
result3 = text_splitter.split_documents([Document(page_content="a b c d e f", metadata={"id": "1"})])
print(f'result3--->{result3}')

运行结果:


除了CharacterTextSplitter分割器,LangChain还支持其他文档分割器 (部分):

分割器名称 功能描述 类型 工业场景应用
CharacterTextSplitter 简单按指定分隔符(如换行、逗号)直接分割。 基础字符解析 简单字符串或 CSV 数据处理,如传感器数据日志。
RecursiveCharacterTextSplitter 递归按字符分割,先尝试自然边界(如段落、句子),太大则继续细分。 通用字符解析 通用文本处理,如日志、报告、PDF 文档分割,便于 RAG 检索。
TokenTextSplitter 按 token(词元)分割,支持 LLM token 计数。 Token 基于解析 LLM 输入优化,如处理 API 响应或长查询,控制 token 限制。
SentenceTextSplitter 按句子边界分割,使用 NLP 识别句子(包括标点)。 语义解析 自然语言文本,如文章或对话分析,保持句子完整。
SpacyTextSplitter 使用 SpaCy NLP 库按句子或实体分割(需安装 SpaCy)。 语义解析 高级 NLP 场景,如实体提取或生物医学文本。
NLTKTextSplitter 使用 NLTK 库按句子或词分割(需安装 NLTK)。 语义解析 文本研究或分析,如时间序列数据描述。
MarkdownHeaderTextSplitter 按 Markdown 结构(如标题、列表)智能分割。 结构化解析 Markdown 文档分割,保留语义结构,用于知识库构建。
HTMLSplitter 按 HTML 标签(如 、)分割网页内容。 结构化解析 网页数据爬取,如在线技术文档或新闻提取。
LatexTextSplitter 按 LaTeX 结构(如章节、公式)分割。 结构化解析 学术论文或数学文档处理。
PythonCodeTextSplitter 按 Python 代码结构(如函数、类)分割。 代码解析 源代码文件分析,如脚本调试或代码库管理。

下面就几个重要的分割器进行讲解。

  • 递归字符文本分割器(RecursiveCharacterTextSplitter)

递归字符文本分割器是一种更智能的分割方法,它尝试在特定分隔符处分割文本,以保持更好的语义完整性。 特点:

  • 尝试在自然断点处分割文本
  • 比简单的字符分割更能保持语义完整性
  • 适用于结构化程度较高的文本,如 Markdown、HTML 等

运行流程:

  • 首先尝试使用第一个分隔符(如 "\n\n")分割文本
  • 如果分割后的块仍然过大,则使用下一个分隔符继续分割
  • 重复此过程,直到达到指定的 chunk_size 或用完所有分隔符

示例代码

python 复制代码
from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=20,  # 每个块最多 100 个字符
    chunk_overlap=6,  # 相邻分块会共享 20 个字符
    length_function=len,  # 用字符数来衡量长度
    separators=["\n\n", "\n", " ", ""]  # 会优先尝试按 \n\n 分段,如果太长,再按 \n → 空格 → 逐字符切分。
)

text = """
人工智能正在快速发展,尤其是大语言模型的应用,正在改变人类的工作方式。
它们可以帮助人们进行写作、代码生成、甚至是科研探索。
相比之下,新能源的发展同样重要。
电动车和太阳能正在逐渐替代传统能源,减少碳排放,对全球环境保护至关重要。
"""
docs = text_splitter.split_text(text)
print(docs)

运行结果

  • 语义文档分割器(SemanticChunker)

语义文档分割器使用语义理解来分割文本,这是一种更高级的分割方法。 特点:

  • 基于语义相似性分割文本
  • 能够更好地保持语义完整性
  • 计算成本较高,处理大量文本时可能效率较低
  • 适用于需要高度语义理解的场景

示例代码

python 复制代码
from langchain_experimental.text_splitter import SemanticChunker
from langchain_ollama import OllamaEmbeddings

embed = OllamaEmbeddings(model="mxbai-embed-large")

text_splitter = SemanticChunker(
     embeddings=embed,
     breakpoint_threshold_type='percentile',
     # 更低的百分位会更"积极"地切分(数值越小 => 切得越多)
     breakpoint_threshold_amount=70.0,
     # 句子拆分正则为同时识别中/英文终结符
     sentence_split_regex=r'(?<=[。!?.!?])\s*',
     # 每个切分后片段(chunk)至少要有多少个字符
     min_chunk_size=10
    )

text = """
人工智能正在快速发展,尤其是大语言模型的应用,正在改变人类的工作方式。
它们可以帮助人们进行写作、代码生成、甚至是科研探索。
相比之下,新能源的发展同样重要。
电动车和太阳能正在逐渐替代传统能源,减少碳排放,对全球环境保护至关重要。
"""

docs = text_splitter.split_text(text)
for i, d in enumerate(docs):
     print(f"------ Chunk {i+1} ------")
     print(d.strip())
     print()

运行结果

  • MarkdownHeaderTextSplitter(Markdown文档切割器)

适用于Markdown文档,按照标题进行拆分

示例代码

python 复制代码
from langchain_text_splitters import MarkdownHeaderTextSplitter

headers_to_split_on = [
("#", "Header 1"),
("##", "Header 2"),
("###", "Header 3"),
]

markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)

markdown_text = "# Header 1\nSome text\n## Header 2\nMore text\n### Header 3\nEven more text"
docs = markdown_splitter.split_text(markdown_text)
print(docs)

运行结果

其他拓展知识可以参考:blog.csdn.net/qq_28540861...

3 VectorStores

VectorStores是一种特殊类型的数据库,它的作用是存储由嵌入创建的向量,提供相似查询等功能。

LangChain支持的VectorStore有python.langchain.com/docs/integr...,常见的如下:

我们使用其中一个Chroma 组件作为例子:

pip install chromadb

pip install langchain-chroma

python 复制代码
from langchain_text_splitters import CharacterTextSplitter
from langchain_chroma import Chroma
from langchain_community.document_loaders import TextLoader
from langchain_ollama import OllamaEmbeddings

# 1.加载文档
# 创建 TextLoader 对象
loader = TextLoader('./data/pku.txt', encoding='utf-8')
# 加载文档
docs = loader.load()
# print(f'docs-->{docs}')

# 2.将文档进行分块
# 创建 CharacterTextSplitter 对象
text_splitter = CharacterTextSplitter(separator="\n\n", chunk_size=200, chunk_overlap=30)
# 分块
split_docs = text_splitter.split_documents(docs)
print(f'split_docs-->{split_docs}')

# 3.将分割后的文档存储到向量数据库中
# 加载embedding模型
embedding = OllamaEmbeddings(model="mxbai-embed-large")
# 创建向量数据库,需要指定 存储的文档和向量模型名称以及持久化目录
chromadaDB = Chroma.from_documents(documents=split_docs,
                                   embedding=embedding,
                                   persist_directory='./chroma_db')

# 假如你的向量数据库已经存在,那么可以直接加载
# chromadaDB = Chroma(persist_directory='./chroma_db', embedding_function=embedding)

# 4.使用向量数据库进行查询
query = "1937年北京大学发生了什么?"
result = chromadaDB.similarity_search(query, k=2)
print(f'result-->{result}')

运行结果:

4 检索器

4.1 LangChain的检索器定义

检索器是 LangChain 中负责信息检索的模块,通常与 索引(Indexes) 模块(如向量存储、嵌入模型)结合使用。它的核心功能是:

  • 输入:接收用户查询(通常是文本)。
  • 处理:根据查询从数据源中检索相关内容。
  • 输出:返回一组相关文档或文本片段(通常是 Document 对象列表)。

检索器在以下场景中扮演关键角色:

  • 问答系统:从文档或知识库中检索答案的上下文。
  • 语义搜索:根据查询的语义返回相关结果。
  • 上下文增强:为语言模型提供外部知识,解决其知识局限。

4.2 检索器的工作原理

检索器通常与 向量存储(Vector Stores) 配合,通过嵌入模型(Embedding Models)将查询和文档转为向量,基于相似性进行检索。工作流程可以分为以下步骤:

  • 查询嵌入:将用户查询通过嵌入模型(如 OpenAIEmbeddings)转为向量表示
  • 相似性搜索:在向量存储中查找与查询向量最相似的文档向量。
  • 文档返回:返回匹配的文档(包含内容、元数据等)。
  • 后处理(可选):对检索结果进行排序、过滤或重新排名。

检索器的核心依赖:

  • 嵌入模型:将文本转为向量(如 OpenAIEmbeddings, HuggingFaceEmbeddings)。
  • 向量存储:存储文档向量(如 Chroma、FAISS、Pinecone)。
  • 相似性度量:如余弦相似度、欧几里得距离

4.3 检索器类型

langchain支持很多检索器python.langchain.com/docs/integr...,部分如下:

此处我们讲解VectorStoreRetriever。

在 LangChain 中,as_retriever() 方法的 search_type 参数决定了向量检索的具体算法和行为。

python 复制代码
retriever = vector_store.as_retriever(
    search_type="similarity",  # 可选 "similarity"|"mmr"|"similarity_score_threshold"
    search_kwargs={
        "k": 5,  # 返回结果数量
        "score_threshold": 0.7,  # 仅当search_type="similarity_score_threshold"时有效,低于阈值的都丢弃。
        "filter": {"source": "重要文档.pdf"},  # 元数据过滤,只会检索满足条件的文档。
        "lambda_mult": 0.25  # 仅MMR搜索有效(控制多样性):接近 0 则更强调和查询的相关性;接近 1 则更强调结果之间的差异性
    }
)

以下是三种搜索类型的对比:

示例代码:

python 复制代码
from langchain_chroma import Chroma
from langchain_ollama import OllamaEmbeddings

embedding = OllamaEmbeddings(model="mxbai-embed-large")

# 向量数据库已经存在,那么可以直接加载
chromadaDB = Chroma(persist_directory='./chroma_db', embedding_function=embedding)

# 使用向量数据库进行查询
query = "1937年北京大学发生了什么?"
# result = chromadaDB.similarity_search(query, k=2)

# 使用 as_retriever 方法返回 Retriever 对象,然后调用 invoke 方法进行查询
retriever = chromadaDB.as_retriever(search_kwargs={"k":2})
result = retriever.invoke(query)
print(f'result-->{result}')

运行结果:

拓展:

vectordb.as_retriever()vectordb.similarity_search() 都是用于从向量数据库中检索相关文档的方法,它们有什么异同:

  • 相同

    • 核心功能:两者都基于向量相似度(如余弦相似度)从向量数据库中检索与查询最相关的文档。
    • 底层技术:通常使用相同的嵌入模型和相似度计算方式(如 FAISS、Chroma、Pinecone 等)。
  • 不同

4.4 拓展

其他几种常用的检索器介绍如下。

  • TFIDFRetriever

功能:基于 TF-IDF(词频-逆文档频率)的检索器。

特点:

  • 使用 TF-IDF 向量表示文档和查询。
  • 适合快速构建原型。
  • 不支持语义搜索。

适用场景:

  • 文本搜索
  • 关键词提取

示例代码:

python 复制代码
from langchain_community.retrievers import TFIDFRetriever
from langchain_core.documents import Document

docs = [
    Document(page_content="量子计算是一种基于量子力学的计算范式。"),
    Document(page_content="人工智能是模拟人类智能的技术。")
]

retriever = TFIDFRetriever.from_documents(docs)
retriever.k = 1  # 返回 1 个结果
results = retriever.invoke("量子计算")
print(results)
  • BM25Retriever

BM25算法:BM25 是对 TF-IDF 的改进版本,在 TF-IDF 基础上做了归一化(防止长文档优势)与饱和控制(防止词频无限增长)。



功能:基于 BM25 算法的关键词检索器,适合基于词频的搜索。

特点:

  • 不依赖嵌入模型,使用词频和逆文档频率(TF-IDF)计算相关性。
  • 适合关键词匹配场景,计算成本低。
  • 不支持语义搜索,效果依赖文本的字面匹配。

适用场景:

  • 传统搜索场景。
  • 关键词驱动的问答。

环境依赖:

pip install rank_bm25

示例代码:

python 复制代码
from langchain_community.retrievers import BM25Retriever
from langchain_core.documents import Document

docs = [
    Document(page_content="量子计算是一种基于量子力学的计算范式。"),
    Document(page_content="人工智能是模拟人类智能的技术。")
]

retriever = BM25Retriever.from_documents(docs)
retriever.k = 1  # 返回 1 个结果
results = retriever.invoke("量子计算")
print(results)
  • MultiQueryRetriever

功能:它借助 LLM 自动生成多个语义等价的改写查询,把用户的问题扩展成多个角度,然后对每个改写进行检索,最后合并结果,以提高召回率。

特点:

  • 使用语言模型生成查询的多种表达方式
  • 从向量存储中检索所有变体的结果并合并
  • 提高召回率,适合复杂查询

适用场景:

  • 查询表达不明确或需要覆盖多种语义
  • 提高检索的全面性
  • EnsembleRetriever

功能:结合多种检索器(如 BM25 和向量存储),融合结果。

特点:

  • 结合关键词搜索和语义搜索的优点
  • 支持加权融合,调整不同检索器的权重
  • 提高召回率和精准度

适用场景:

  • 需要综合关键词和语义的搜索
  • 复杂查询场景
  • ContextualCompressionRetriever

功能:对检索结果进行压缩,提取最相关的内容

特点:

  • 使用语言模型对检索到的文档进行重新排序或精炼
  • 减少无关内容,提高结果质量
  • 增加计算开销,但提升精准度

适用场景:

  • 文档内容冗长,需要提取关键信息
  • 提高问答系统的答案质量
  • Custom Retriever

功能:开发者可以自定义检索逻辑,适配特定数据源或算法

特点:

  • 继承 BaseRetriever 类,实现 get_relevant_documents 方法
  • 支持任意数据源(如数据库、API)

适用场景:

  • 特定领域的数据源(如内部数据库)
  • 自定义检索算法

八、Agents

1 Agent 概念

Agent(智能体)是一种能够感知环境、进行决策和执行动作的智能实体。不同于传统的人工智能,Agent 具备通过主动思考、调用工具去逐步完成给定目标的能力。

为什么要调用工具?

  • 因为大模型虽然非常强大,但是也具备一定的局限性,比如不能回答实时信息、处理数学逻辑问题仍然非常的初级等等。因此,可以借助第三方工具来辅助大模型的应用。

从大模型的角度来看,Agent其实就是基于大模型的语义理解和推理能力,让大模型拥有解决复杂问题时的任务规划能力,并调用外部工具来执行各种任务,利用向量数据库保留"记忆"的一个智能体

Agent = 大模型 + 任务规划(Planning) + 使用外部工具执行任务(Tools&Action) + 记忆(Memory)

把Agent比作一个人的话,他应该有大脑(语义理解、存储记忆、推理规划、专业知识)、五官(接收文本、视觉输入、听觉输入等)、四肢(使用工具完成各种具体任务)等主要部件


工作流程概述:

  • 用户提出任务。
  • Agent 启动: 将用户输入与预设的"提示词模板"结合,并结合当前的"上下文"和"变量",形成一个完整的输入发送给大模型。
  • 大模型思考与决策 (循环):
    • 大模型接收输入后,根据其内置的逻辑和提示词的指导,进行"思考"。
    • 它会判断完成当前任务是需要继续使用工具来获取更多信息/执行操作,还是已经可以直接生成最终答案。
    • 如果需要工具: 大模型会根据任务需求和对工具的描述,选择合适的工具,并生成执行该工具所需的输入参数。这些参数通常会从上下文或变量中提取。
    • 工具执行: 选定的工具被调用,执行其功能。
    • 结果反馈: 工具执行的结果会返回给 Agent,并被用来更新"上下文"和"变量"。
    • 循环: Agent 将更新后的"上下文"、"变量"以及工具执行结果再次反馈给大模型,大模型继续进行新一轮的"思考-行动"循环,直到任务完成。
    • 如果直接回答: 当大模型判断任务已完成,或无需额外工具即可回答时,它会生成最终的答案。
  • 用户输出: 最终答案被呈现给用户。

2 Agent关键组成部分

  • 任务规划(Planning)

    Agent需要提前将一项复杂任务拆解为多个更小、更易于处理的子任务,从而实现对复杂任务的高效处理

  • 长短期记忆(Memory)

    聊天上下文,长期保留和回忆信息

  • 工具&执行(Tools&Action)

    根据拆分好的子任务,调用外部提供好的专业API解决专业问题,完成一个个具体的子任务,并把处理结果返回给大模型

3 langchain实现Agent

LangChain 提供了不同类型的代理(主要罗列一下三种):

  • Zero-shot ReAct Description

    • 基于 ReAct 框架 (推理 + 行动),仅依赖工具的 描述 来决定调用哪个工具。

    • 特点:无需额外示例(zero-shot),但 不具备记忆能力,每次推理都独立进行。

    • 使用场景:简单任务,工具选择完全靠工具描述即可。

  • Structured Chat Zero-shot ReAct Description

    • 同样基于 ReAct 框架 ,但可以处理 结构化输入,即支持带多个参数的工具(类似函数调用)。

    • 特点:不仅能像第一种代理那样根据描述选择工具,还能正确组织并传递复杂参数。

    • 使用场景:调用接口类工具、需要多参数输入的任务。

  • Conversational ReAct Description

    • 在 ReAct 框架基础上,增强了 对话记忆能力

    • 特点:能根据上下文对话历史来做出工具选择和回应,更适合持续性对话场景。

    • 使用场景:多轮对话,用户可能引用之前的内容或需要长期上下文跟踪。


LangChain 中集成了很多工具,可以通过下面的方式进行查询:

python 复制代码
from langchain_community.agent_toolkits.load_tools import get_all_tool_names
results = get_all_tool_names()
print(results)

运行结果:

css 复制代码
['sleep', 'wolfram-alpha', 'google-search', 'google-search-results-json', 'searx-search-results-json', 'bing-search', 'metaphor-search', 'ddg-search', 'google-books', 'google-lens', 'google-serper', 'google-scholar', 'google-finance', 'google-trends', 'google-jobs', 'google-serper-results-json', 'searchapi', 'searchapi-results-json', 'serpapi', 'dalle-image-generator', 'twilio', 'searx-search', 'merriam-webster', 'wikipedia', 'arxiv', 'golden-query', 'pubmed', 'human', 'awslambda', 'stackexchange', 'sceneXplain', 'graphql', 'openweathermap-api', 'dataforseo-api-search', 'dataforseo-api-search-json', 'eleven_labs_text2speech', 'google_cloud_texttospeech', 'read_file', 'reddit_search', 'news-api', 'tmdb-api', 'podcast-api', 'memorize', 'llm-math', 'open-meteo-api', 'requests', 'requests_get', 'requests_post', 'requests_patch', 'requests_put', 'requests_delete', 'terminal']

接下来,通过一个示例来学习Agent的基本使用。

  • 问题1:计算一下300的25%是多少?
  • 问题2:请帮我介绍一下故宫

示例代码:

需要提前安装 wikipedia

pip install wikipedia

python 复制代码
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.memory import MemorySaver
from langchain.agents import create_agent
from langchain_community.agent_toolkits.load_tools import load_tools
from langchain_openai import ChatOpenAI
import  os

# 实例化模型
model = ChatOpenAI(
    base_url=os.environ.get('base_url','https://dashscope.aliyuncs.com/compatible-mode/v1'),
    model='qwen-plus',
    openai_api_key=os.environ.get('api_key','sk-XXXXXXXX'),
    max_tokens=1000,
    temperature=0
)

# Create the agent
memory = MemorySaver()
tools = load_tools(['wikipedia', 'llm-math'], llm=model)
agent_executor = create_agent(model, tools, checkpointer=memory)

# Use the agent
config = {"configurable": {"thread_id": "abc123"}}

for chunk in agent_executor.stream(
    {"messages": [HumanMessage(content="计算一下300的25%是多少?")]}, config
):
    print(chunk)
    print("----")

# for chunk in agent_executor.stream(
#     {"messages": [HumanMessage(content="大熊猫是哪个国家的国宝?")]}, config
# ):
#     print(chunk)
#     print("----")

运行结果:

参考官网 python.langchain.com/docs/how_to...

九、LangChain使用场景

  • 个人助手
  • 基于文档的问答系统
  • 聊天机器人
  • Tabular数据查询
  • API交互
  • 信息提取
  • 文档总结
相关推荐
YHL1 小时前
🤖 Agent 智能体开发实战 · 第一课:Tool Use —— 让大模型自动干活
前端·javascript·人工智能
萧萧秦风瘦飞马1 小时前
CSDN博客-第6天-DataLoader与二维非线性分类
人工智能·分类·数据挖掘
Java小白笔记1 小时前
Codex config.toml配置实战指南
人工智能·算法·chatgpt·ai编程·集成学习
Goodbye1 小时前
AI 数据集:大模型智能的基石
人工智能
AKAMAI1 小时前
Akamai收购安全企业浏览器提供商LayerX
人工智能·云计算
用户2749329676611 小时前
Spring AI 手搓 RAG:文档上传 → 向量化 → 检索增强,全链路 Java 实现
人工智能
米小虾1 小时前
Claude Code Loop Engineering 深度解读:从写 Prompt 到设计 Loop
人工智能·agent
科技侃谈2 小时前
上海、安徽、浙江、江苏制造业智能仓储服务商选型指南:机器人零部件企业的破局之选
人工智能