LangChain笔记 (自用)

0 阅读6分钟

一、基本结构与概念

什么是 LangChain

LangChain 是一个用于构建大语言模型应用的开发框架。它提供了一系列标准化的组件和接口,让开发者能够轻松地将大模型与外部工具、数据源连接起来,构建复杂的 AI 应用。

核心价值

  • 标准化:统一的接口和组件
  • 可组合:像搭积木一样组合功能
  • 可扩展:支持自定义组件和第三方集成

1. Models(模型)

LangChain 统一封装了各种大模型的调用接口。

from langchain_community.chat_models import ChatTongyi from langchain_openai import ChatOpenAI from langchain_community.llms import Ollama

通义千问

llm_tongyi = ChatTongyi( api_key="your-api-key", model_name="qwen-turbo" )

OpenAI

llm_openai = ChatOpenAI( api_key="your-api-key", model="gpt-3.5-turbo" )

本地模型

llm_local = Ollama( model="llama2", base_url="http://localhost:11434" )

统一调用方式

response = llm_tongyi.invoke("你好") print(response.content) # 输出:你好!有什么我可以帮助你的吗?

2. Prompts(提示词)

管理、格式化、优化提示词的工具。

from langchain_core.prompts import (
    PromptTemplate,           # 基础模板
    ChatPromptTemplate,       # 对话模板
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate
)

# 基础提示词模板
template = PromptTemplate.from_template(
    "请用{style}的风格写一首关于{topic}的诗"
)
prompt = template.format(style="浪漫", topic="月亮")
# 输出:请用浪漫的风格写一首关于月亮的诗

# 对话提示词模板
chat_template = ChatPromptTemplate.from_messages([
    ("system", "你是一个{role}专家"),
    ("user", "{question}")
])
prompt = chat_template.format(role="历史学家", question="秦始皇统一六国的意义")

3. Output Parsers(输出解析器)

将模型输出解析为结构化数据。

from langchain_core.output_parsers import (
    StrOutputParser,      # 字符串解析器
    JsonOutputParser,     # JSON解析器
    CommaSeparatedListOutputParser  # 列表解析器
)

# 字符串解析器
parser = StrOutputParser()
result = parser.parse("这是一段文本")  # 直接返回字符串

# JSON解析器
json_parser = JsonOutputParser()
result = json_parser.parse('{"name": "张三", "age": 25}')
# 输出:{'name': '张三', 'age': 25}

# 列表解析器
list_parser = CommaSeparatedListOutputParser()
result = list_parser.parse("苹果,香蕉,橘子")
# 输出:['苹果', '香蕉', '橘子']

4. Chains(链)

将多个组件串联起来形成完整的处理流程。

from langchain_core.runnables import RunnableSequence

# 方式1:使用管道操作符
chain = prompt | llm | parser

# 方式2:使用 RunnableSequence
chain = RunnableSequence(prompt, llm, parser)

# 调用链
result = chain.invoke({"topic": "人工智能"})

5. 流式

流式调用是指大模型在生成内容时,边生成边返回,而不是等全部生成完再一次性返回。就像打字机一样,一个字一个字地显示出来。

对比示例

  • 普通调用:等待10秒 → 一次性显示完整文章
  • 流式调用:边生成边显示 → 逐字出现,用户体验更流畅

在 LCEL 链中使用流式输出。

# 构建链
chain = prompt | llm | parser

# 流式执行
for chunk in chain.stream({"question": "写一首诗"}):
    print(chunk, end="", flush=True)

每个流式返回的 chunk 包含:

chunk = {
    "content": "本次返回的文本",  # 文本内容
    "additional_kwargs": {},      # 额外信息
    "response_metadata": {        # 响应元数据
        "model": "qwen-turbo",
        "finish_reason": None,    # 最后一块会显示 stop
        "token_usage": {}         # 令牌使用情况(仅最后一块)
    }
}

大模型生成文本时,本质上是预测下一个 token 的过程:

  • 模型逐字生成:token1 → token2 → token3 → ... → tokenN
  • 流式调用每生成一个 token 就返回一次
  • 客户端每收到一个 token 就立即显示

二、记忆系统

(一)记忆

1.为什么要有记忆系统

A:上下文保持 个性化交互 长期学习

历史内容变多,token变多,收费也就随之变多

2.ConversationBufferMemory(缓冲记忆)

1)完整的存储所有的记忆,适合完整的上下文

2)Token消随着对话耗线性增长,可能超出窗口内存

3.ConversationBufferWindowMemory

是LangChain提供的一种记忆机制,它只存储最近的K条对话记录(包括用户输入和模型输出)。这里的k指的是用户指定的窗口大小,表示保留多少轮对话,确保Token在可控范围内。 memory = ConversationBufferWindowMemory(k =1)

9808ce02e422cc2c2c08ff80019f2fe5.png 4.ConversationTokenBufferMemory根据Token数量来限制存储对话历史,用户可以指定一个最大的Token数

特点:Token驱动截断;模型适配性(不同模型token不同);动态窗口;高效存储

缺点:更依赖LLM,需要LLM的Token存取规则;可能丢失早期信息 ;设置复杂性;不适合需要完整历史的场景信息

5.ConversationSummaryBufferMemory

一种混合型记忆机制,结合了buffer和Summary

近期对话:直接存储最近的对话内容为原始内容

早期对话:对话历史超过指定的Token限制时,系统会调用llm将早期的对话总结为紧凑的文字,替换原始内容

动态管理:通过总结早期对话并保留近期对话,保持上下文在Token限制内,保留关键信息,同时仍能提供长期上下文支持。

特点: 混合存储机制;Token驱动截断;依赖LLM进行总结;动态平衡;

缺点:依赖LLM总结;额外设计开销(生成对话总结需要额外的LLM调用,增加成本和响应时间);复杂性较高;不适合短对话

(二)查询记忆

printf(memory.buffer) printf(memory.load_memory_variables({}))

verbose = True #打印调试信息

image.png

image.png

三、文本嵌入模型

(一)文本模型(向量)

Q:什么是文本嵌入

A:将文本信息转换为固定长度的数值向量,电脑不认识文字,但是认识数字

向量捕捉文本的语义信息,相似的语义在向量空间距离较近 例如 hi hello 可以用来做推荐,跨语言也可以(相似度矩阵,TextBox)

image.png

image.png

(二)搭建本地文本模型

1.示例:

image.png

image.png

2.分文调用分类示例

image.png

3.数据持久化

pip install chromadb

示例为使用本地模型embeddings,documents为上面已经分好块的splite;

similarity_search为匹配数据;

PS:网络版和本地版维度可能不同而报错,因为网络版在第一次运行时,在本地已经产生了文件,再次运行无法替换。

image.png

四、工具封装

(一)基本概念

1.为什么需要工具调用?

A:解决LLM的局限性:大模型会出现幻觉问题,且无法直接访问实时数据或者执行具体操作;

扩展边界能力:通过工具集成,Agent可以获得计算API访问等能力;

模块化设计;

@tool装饰器 用于将普通Python函数转化为LangChain工具; 自动生成JSON Schema,描述工具的输入参数和功能;

示例: @tool def add(a:int,b:int)->int: return a+b ;

Json Schema规范: 工具输入需要明确的参数;文档字符串描述功能

相关API 可以在网络中找到开源如: APISpace

image.png

(二)封装天气事例

request//向其他服务器发送请求

panda//将不同平台的编码城市转换(读取) image.png

image.png CSV格式数据

动态查询事例

image.png

调用实战

1.先创建工具列表

image.png

2.智能体创建+调用

image.png

image.png

工作原理(ReAct Agent 的自动调用机制) 当你调用 agent.invoke() 时,内部发生了以下步骤: LLM 分析问题 → "现在是几点?" LLM 查看可用工具列表 → 发现有 get_current_time 工具 LLM 决定调用工具 → 生成工具调用指令 LangGraph 执行工具 → 实际运行 get_current_time() 函数 返回结果给 LLM → "2026-04-01 14:30:00" LLM 组织语言回答 → "现在的时间是..."