Skip to content

LLMOps API 学习总文档

本文档汇总了 LangChain 框架核心组件的学习笔记,涵盖从基础组件到高级应用的完整学习路径。


目录

  1. Prompt组件及使用技巧
  2. Model组件及使用技巧
  3. OutputParser组件及使用技巧
  4. LCEL表达式与Runnable可运行协议
  5. 两个Runnable核心类的讲解与使用
  6. 利用回调功能调试链应用
  7. Python+OpenAI原生SDK实现记忆功能
  8. ChatMessage组件上手与源码解析
  9. 缓冲窗口记忆组件
  10. Runnable组件动态添加默认调用参数

1. Prompt组件及使用技巧

核心组件

组件说明
PromptTemplate基础字符串提示模板
ChatPromptTemplate聊天对话提示模板
MessagesPlaceholder消息占位符,用于动态插入历史消息
HumanMessagePromptTemplate人类消息模板

基础用法

python
from langchain_core.prompts import PromptTemplate

prompt = PromptTemplate.from_template("请讲一个关于{subject}的冷笑话")
result = prompt.invoke({"subject": "程序员"}).to_string()

关键方法

方法说明
from_template()从字符串模板创建
invoke()传入参数生成PromptValue
format()格式化为字符串
partial()预填充部分参数

拼接技巧

字符串拼接

python
prompt = (
    PromptTemplate.from_template("请讲一个关于{subject}的冷笑话")
    + ",让我开心下" +
    "\n使用{language}语言"
)

PipelinePromptTemplate(模块化复用)

python
from langchain_core.prompts import PipelinePromptTemplate

full_template = PromptTemplate.from_template("{instruction}\n\n{example}\n\n{start}")

pipeline_prompts = [
    ("instruction", instruction_prompt),
    ("example", example_prompt),
    ("start", start_prompt)
]

pipeline_prompt = PipelinePromptTemplate(
    final_prompt=full_template,
    pipeline_prompts=pipeline_prompts,
)

技巧对比

技巧适用场景
PromptTemplate简单字符串提示
ChatPromptTemplate对话场景,含多种消息类型
MessagesPlaceholder动态插入历史消息
+ 拼接简单线性组合
PipelinePromptTemplate复杂模块化提示系统

2. Model组件及使用技巧

三种调用方式

方式方法适用场景响应方式
单次调用.invoke()简单请求一次性返回全部内容
批处理.batch()多个并行请求返回所有结果列表
流式输出.stream()长文本/聊天逐块返回生成内容

基础使用

python
from datetime import datetime
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是OpenAI开发的聊天机器人,现在的时间是{now}"),
    ("human", "{query}"),
]).partial(now=datetime.now())

llm = ChatOpenAI(model="moonshot-v1-8k")
ai_message = llm.invoke(prompt.invoke({"query": "你好"}))

批处理示例

python
ai_messages = llm.batch([
    prompt.invoke({"query": "你好"}),
    prompt.invoke({"query": "请讲一个笑话"}),
])

流式输出示例

python
response = llm.stream(prompt.invoke({"query": "介绍一下LLM"}))

for chunk in response:
    print(chunk.content, flush=True, end="")

使用技巧

使用 .partial() 预填充静态变量

  • 减少重复传参
  • 提高代码可读性
  • 适合系统提示词中的固定参数

3. OutputParser组件及使用技巧

StrOutputParser - 字符串输出解析器

功能:将LLM的输出转换为纯字符串格式

适用场景

  • 简单的问答场景
  • 文本生成任务
  • 不需要结构化输出的场景
python
from langchain_core.output_parsers import StrOutputParser

parser = StrOutputParser()
content = parser.invoke(llm.invoke(prompt.invoke({"query": "你好"})))

JsonOutputParser - JSON输出解析器

功能:将LLM的输出解析为JSON格式的结构化数据

适用场景

  • 需要结构化输出的场景
  • 提取特定字段信息
  • 后续需要程序化处理输出的场景
python
from langchain_core.output_parsers import JsonOutputParser
from pydantic import BaseModel, Field

class Joke(BaseModel):
    joke: str = Field(description="回答用户的冷笑话")
    punchline: str = Field(description="这个冷笑话的笑点")

parser = JsonOutputParser(pydantic_object=Joke)

prompt = ChatPromptTemplate.from_template(
    "请根据用户的提问进行回答。\n{format_instructions}\n{query}"
).partial(format_instructions=parser.get_format_instructions())

joke = parser.invoke(llm.invoke(prompt.invoke({"query": "请讲一个笑话"})))

执行流程

定义BaseModel → 创建JsonOutputParser → 获取格式说明 → 构建Prompt → LLM生成 → 解析为字典

4. LCEL表达式与Runnable可运行协议

核心概念

Runnable 协议

  • invoke(input): 同步调用
  • batch(inputs): 批量调用
  • stream(): 流式输出

LCEL (LangChain Expression Language)

  • 使用管道操作符 | 连接组件
  • 声明式的链式调用语法

LCEL 链式调用示例

python
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

prompt = ChatPromptTemplate.from_template("{query}")
llm = ChatOpenAI(model="moonshot-v1-8k")
parser = StrOutputParser()

# 使用 LCEL 创建链
chain = prompt | llm | parser

result = chain.invoke({"query": "请讲一个程序员的冷笑话"})

数据流转过程

输入: {"query": "你好"}

Prompt (模板) → "你好"

LLM (模型) → AIMessage(content="我是AI助手...")

Parser (解析器) → "我是AI助手..."

输出: "我是AI助手..."

最佳实践

  1. 使用 LCEL 语法:简洁且易于维护
  2. 理解组件职责:每个组件只做一件事
  3. 注意数据类型:确保上下游组件的输入输出类型匹配
  4. 调试技巧:在链中加入自定义处理步骤打印中间结果

5. 两个Runnable核心类的讲解与使用

RunnableParallel - 并行执行

功能:并行执行多个 Runnable 对象,将结果组合成字典返回

优势

  • 提高执行效率
  • 结果聚合
  • 简化代码
python
from langchain_core.runnables import RunnableParallel

joke_chain = joke_prompt | llm | parser
poem_chain = poem_prompt | llm | parser

# 并行执行
map_chain = RunnableParallel(joke=joke_chain, poem=poem_chain)

res = map_chain.invoke({"subject": "程序员"})
# 输出: {'joke': '...', 'poem': '...'}

RunnablePassthrough - 数据透传

功能:在链中传递原始输入数据,通过 assign 添加新字段

优势

  • 简化链的构建
  • 保留原始输入
  • 动态添加字段
python
from langchain_core.runnables import RunnablePassthrough

chain = RunnablePassthrough.assign(
    context=lambda x: retrieval(x["query"])
) | prompt | llm | parser

工具类对比

工具类主要用途典型场景
RunnableParallel并行执行多个链,聚合结果同时生成多种内容、并行调用不同模型
RunnablePassthrough透传数据,动态添加字段RAG检索、数据增强处理

RAG 推荐写法

python
chain = RunnablePassthrough.assign(
    context=lambda x: retrieval(x["query"])
) | prompt | llm | parser

6. 利用回调功能调试链应用

是什么

LangChain 回调功能是一种监控和调试链式应用执行过程的机制,基于事件驱动模式。

有什么用

  1. 执行过程可视化 - 实时查看链的执行流程
  2. 性能监控 - 统计各环节执行耗时
  3. 调试与问题定位 - 记录详细的执行日志
  4. 自定义监控告警 - 集成日志系统

常用回调方法

  • on_chat_model_start: 聊天模型开始执行
  • on_chat_model_end: 聊天模型执行结束
  • on_llm_start: LLM 开始执行
  • on_llm_end: LLM 执行结束
  • on_chain_start: 链开始执行
  • on_chain_end: 链执行结束

自定义回调处理器示例

python
import time
from langchain_core.callbacks import BaseCallbackHandler

class LLMOpsCallbackHandler(BaseCallbackHandler):
    start_at: float = 0

    def on_chat_model_start(self, serialized, messages, run_id, **kwargs):
        print("聊天模型开始执行了")
        self.start_at = time.time()

    def on_llm_end(self, response, run_id, **kwargs):
        end_at = time.time()
        print("程序消耗:", end_at - self.start_at)

# 使用回调
resp = chain.stream(
    "你好",
    config={"callbacks": [LLMOpsCallbackHandler()]}
)

实际应用场景

  • 开发调试阶段:快速定位问题,查看中间结果
  • 性能优化:识别耗时环节,对比不同实现的性能
  • 日志审计:记录所有调用记录,追踪用户操作
  • 监控告警:集成到监控系统,设置异常阈值告警

7. Python+OpenAI原生SDK实现记忆功能

是什么

使用 Python 和 OpenAI 原生 SDK 从零实现的摘要缓存混合记忆(ConversationSummaryBufferMemory)系统。

核心原理

摘要缓存混合记忆

┌─────────────────────────────────────┐
│  摘要部分(Summary)                  │
│  存储早期对话的提炼总结                │
└─────────────────────────────────────┘
              ↓ 随对话增长动态生成
┌─────────────────────────────────────┐
│  缓冲部分(Buffer)                   │
│  存储最近的完整对话记录                │
└─────────────────────────────────────┘

工作流程

  1. 初始阶段:所有对话存储在缓存中
  2. 触发摘要:当缓存token数超过 max_tokens 阈值时
  3. 生成摘要:将最早的对话与现有摘要合并
  4. 移除旧对话:将已摘要的对话从缓存中删除
  5. 循环进行:保持对话历史的可控性

核心类实现

python
class ConversationSummaryBufferMemory:
    def __init__(self, summary: str = '', chat_histories: list = None, max_tokens: int = 300):
        self.summary = summary
        self.chat_histories = [] if chat_histories is None else chat_histories
        self.max_tokens = max_tokens
        self.client = OpenAI(base_url='https://api.moonshot.cn/v1')

    def save_content(self, human_query: str, ai_content: str) -> None:
        # 保存新对话并检查是否需要生成摘要
        self.chat_histories.append({'human': human_query, 'ai': ai_content})

        if self.get_num_tokens(self.get_buffer_string()) > self.max_tokens:
            first_chat = self.chat_histories[0]
            self.summary = self.summary_text(self.summary, f"human: {human_query}\nai: {first_chat.get('ai')}")
            del self.chat_histories[0]

    def load_memory_variables(self) -> dict:
        buffer_string = self.get_buffer_string()
        return {"chat_history": f"摘要: {self.summary}\n历史信息:{buffer_string}"}

应用场景

场景优势
智能客服记住用户问题和历史投诉
个性化助手记住用户偏好和习惯
教育辅导跟踪学习进度和知识点
心理咨询保持长期咨询的连贯性

8. ChatMessage组件上手与源码解析

是什么

ChatMessage 是 LangChain 框架中用于管理和存储对话历史的组件。

主要实现类

InMemoryChatMessageHistory(内存存储)

用途:将对话历史存储在内存中

优点:速度快、无需额外配置 缺点:程序重启后数据丢失

python
from langchain_core.chat_history import InMemoryChatMessageHistory

chat_history = InMemoryChatMessageHistory()
chat_history.add_user_message("你好,我是ccc")
chat_history.add_ai_message("你好,我是chatgpt")
print(chat_history.messages)

FileChatMessageHistory(文件存储)

用途:将对话历史持久化到文件中

优点:数据持久化、跨会话记忆 缺点:读写速度相对内存慢

python
from langchain_community.chat_message_histories import FileChatMessageHistory

chat_history = FileChatMessageHistory('./memory.txt')
chat_history.add_user_message("你好")
chat_history.add_ai_message("你好!")

常用API方法

方法说明
add_user_message(message)添加用户消息
add_ai_message(message)添加 AI 消息
messages 属性获取所有消息
clear()清空历史

使用场景对比

场景推荐组件原因
简单对话机器人InMemoryChatMessageHistory无需持久化,简单快速
客服系统FileChatMessageHistory需要保存对话记录
聊天应用FileChatMessageHistory用户需要历史记录

9. 缓冲窗口记忆组件

是什么

缓冲窗口记忆组件(Buffer Window Memory)是一种带有限容量的对话历史管理机制

有什么用

  1. 节省API成本 - 限制历史Token数控制成本
  2. 提升响应速度 - 减少每次请求的输入Token数量
  3. 避免超出上下文窗口 - 防止历史记录过多超出模型处理能力
  4. 保持对话连贯性 - 在Token限制内保留最近的对话内容

实现方式对比

方式一:SimpleMemory(手动实现)

python
class SimpleMemory:
    def __init__(self, max_token_limit=2000):
        self.history = []
        self.max_token_limit = max_token_limit

    def _trim_history(self):
        total_chars = sum(len(msg.content) for msg in self.history)
        max_chars = self.max_token_limit * 4

        while total_chars > max_chars and len(self.history) > 2:
            removed = self.history.pop(0)
            total_chars -= len(removed.content)

方式二:RunnableWithMessageHistory(集成方案)

python
from langchain_core.runnables.history import RunnableWithMessageHistory

store = {}

def get_session_history(session_id: str):
    if session_id not in store:
        store[session_id] = FileChatMessageHistory(f"chat_history_{session_id}.txt")
    return store[session_id]

with_message_chain = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key="query",
    history_messages_key="history",
)

关键参数

参数说明推荐值
max_token_limit最大Token数量限制2000-4000
session_id会话唯一标识符用户ID或会话UUID

最佳实践

  1. 合理设置Token限制(根据模型上下文窗口大小)
  2. 持久化存储建议使用数据库(Redis、PostgreSQL等)
  3. 为每个用户或会话分配唯一的session_id
  4. 考虑使用异步操作提升并发性能

10. Runnable组件动态添加默认调用参数

是什么

bind() 是 Runnable 组件的方法,用于动态添加默认调用参数

有什么用

  • 简化调用 - 提前绑定固定参数
  • 参数复用 - 避免每次 invoke 都重复传相同参数
  • 多参场景 - 解决 RunnableLambda 只能接收单参的问题
  • 动态覆盖 - 在链式调用中动态修改 LLM 参数

示例1:RunnableLambda 预设默认参数

python
from langchain_core.runnables import RunnableLambda

def get_weather(location: str, unit: str, name: str) -> str:
    return f"{name}你好,查询到{location}的天气是25度{unit}"

# 绑定 unit 和 name,调用时只需传 location
get_weather_runnable = RunnableLambda(get_weather).bind(unit="摄氏度", name="muxiaoke")

res = get_weather_runnable.invoke("广州")
# 输出: muxiaoke你好,查询到广州的天气是25度摄氏度

示例2:LLM 链式调用中动态覆盖模型参数

python
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

prompt = ChatPromptTemplate.from_messages([("human", "{query}")])
llm = ChatOpenAI(model="moonshot-v1-8k")

# 使用 bind 动态覆盖 model 参数,从 8k 切换到 32k
chain = prompt | llm.bind(model="moonshot-v1-32k") | StrOutputParser()

content = chain.invoke({"query": "你好,你是什么模型"})
# 实际使用的是 moonshot-v1-32k 模型

总结

本学习路径涵盖了 LangChain 框架从基础到高级的核心知识:

  1. 基础组件(Prompt、Model、OutputParser)
  2. LCEL表达式与Runnable协议
  3. 高级组件(RunnableParallel、RunnablePassthrough)
  4. 调试技巧(回调功能)
  5. 记忆管理(原生实现、ChatMessage、缓冲窗口)
  6. 高级技巧(bind函数)

通过系统学习这些组件,可以构建生产级的 LLM 应用程序。