LangChain 提示词模板与链式调用笔记

文章目录

  • [1. PromptTemplate 与 ChatPromptTemplate 的区别](#1. PromptTemplate 与 ChatPromptTemplate 的区别)
    • [1.1 PromptTemplate -- 单字符串输出](#1.1 PromptTemplate – 单字符串输出)
    • [1.2.ChatPromptTemlate -- 消息列表输出](#1.2.ChatPromptTemlate – 消息列表输出)
    • [1.3 MessagesPlaceholder -- 动态插入历史对话](#1.3 MessagesPlaceholder – 动态插入历史对话)
    • [1.4 对比表格](#1.4 对比表格)
  • [2. 基础链式调用](#2. 基础链式调用)
    • [2.1 链式调用的核心概念](#2.1 链式调用的核心概念)
    • [2.2 最简单的链:提示词模板 + 模型](#2.2 最简单的链:提示词模板 + 模型)
    • [2.3 输出解析器:StrOutputParser](#2.3 输出解析器:StrOutputParser)
    • [2.4 完整 FastAPI 示例](#2.4 完整 FastAPI 示例)
  • [3. JsonOutputParser:将模型输出解析为字典](#3. JsonOutputParser:将模型输出解析为字典)
    • [3.1 基本概念](#3.1 基本概念)
    • [3.2 基础用法](#3.2 基础用法)
  • [4. 多模型链式调用与 RunnableLambda](#4. 多模型链式调用与 RunnableLambda)
    • [4.1 多模型链的概念](#4.1 多模型链的概念)
    • [4.2 链的基本结构](#4.2 链的基本结构)
    • [4.3 RunnableLambda:将任意函数转换为 Runnable](#4.3 RunnableLambda:将任意函数转换为 Runnable)
      • [4.3.1 语法与用法](#4.3.1 语法与用法)
    • [4.4 完整示例:两次模型调用 -- "起名 + 解析含义"](#4.4 完整示例:两次模型调用 – “起名 + 解析含义”)
  • [5. 向量数据库(Chroma)](#5. 向量数据库(Chroma))
    • [5.1 安装向量数据库](#5.1 安装向量数据库)
    • [5.2 用法](#5.2 用法)
    • [5.3 关键说明](#5.3 关键说明)
  • [6. 数据分割](#6. 数据分割)
  • 7.Memory
    • [7.1Memory 临时会话](#7.1Memory 临时会话)
    • [7.2 长期会话](#7.2 长期会话)
  • [8.LangchainV1.下与V0.3 比较](#8.LangchainV1.下与V0.3 比较)
  • [8.1统一Agent创建接口 create_agent()](#8.1统一Agent创建接口 create_agent())
    • [8.2 中间件系统(Middleware)](#8.2 中间件系统(Middleware))
      • [8.2.3 自定义中间件](#8.2.3 自定义中间件)
      • [8.2.3.1 围绕模型-修饰器](#8.2.3.1 围绕模型-修饰器)
      • [8.2.3.2 围绕模型-类](#8.2.3.2 围绕模型-类)
    • [8.3 Langchain是一个构建LLM应用的核心框架](#8.3 Langchain是一个构建LLM应用的核心框架)
  • [9.Langchin 实现RAG(检索增强生成)](#9.Langchin 实现RAG(检索增强生成))
    • [10.1 多路召回概述](#10.1 多路召回概述)

1. PromptTemplate 与 ChatPromptTemplate 的区别

1.1 PromptTemplate -- 单字符串输出

PromptTemplate 用于传统的文本补全模型(如 text-davinci-003),输出一个纯字符串。

python 复制代码
from langchain_core.prompts import PromptTemplate

prompt = PromptTemplate.from_template("请写一首关于{topic}的诗。")
result = prompt.format(topic="边塞")
print(result)
# 输出:请写一首关于边塞的诗。

1.2.ChatPromptTemlate -- 消息列表输出

ChatPromptTemplate 用于聊天模型(如 GPT-3.5/4、DeepSeek Chat),输出一个 List[BaseMessage],每条消息包含 role 和 content。

python 复制代码
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一位边塞诗人。"),
    ("user", "请写一首关于{topic}的诗。")
])
messages = prompt.format_messages(topic="边塞")
print(messages)
# 输出:[SystemMessage(content='你是一位边塞诗人。'), HumanMessage(content='请写一首关于边塞的诗。')]

1.3 MessagesPlaceholder -- 动态插入历史对话

ChatPromptTemplate 特有的 MessagesPlaceholder 可以动态插入历史对话记录,这是 PromptTemplate 无法直接做到的(除非你手动把历史转成字符串)。

python 复制代码
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是助手"),
    MessagesPlaceholder("history"),
    ("user", "{input}")
])

history_data = [
    ("user", "请给我写一首李白的唐诗"),
    ("assistant", "床前明月光,疑似地上霜。举头望明月,低头思故乡"),
    ("user", "好诗再来一首"),
    ("assistant", "窗含西岭千秋雪,门泊东吴万里船"),
]

# 正确调用
messages = prompt.format_messages(history=history_data, input="你的提问")
print(messages)

1.4 对比表格

特性 PromptTemplate ChatPromptTemplate
适用模型 传统的 文本补全模型(如 GPT-3、text-davinci-003) 聊天模型(如 GPT-3.5/4、DeepSeek Chat、文心一言)
输出内容 一个 单一的字符串(纯文本 prompt) 一个 消息列表(List[BaseMessage]),每条消息有 role(如 system、user、assistant)和 content
输入变量 简单字符串格式化(如 {topic}) 支持结构化历史消息占位符(如 MessagesPlaceholder)
典型使用场景 生成文章、翻译、代码补全等单轮文本生成 多轮对话、带系统指令的聊天、对话记忆管理

2. 基础链式调用

LangChain 允许通过 | 运算符将多个组件串联成一条"链"(Runnable 序列),链中的每个组件都必须实现 Runnable 接口。

2.1 链式调用的核心概念

  • 使用 | 连接各个组件,形成 RunnableSerializable 对象。
  • 调用链的 invoke 方法获得最终结果,或调用 stream 获得流式输出。
  • 典型结构:提示词模板 | 模型 | 输出解析器

2.2 最简单的链:提示词模板 + 模型

python 复制代码
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_deepseek import ChatDeepSeek

# 定义提示词模板
chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一位边塞诗人,可以作诗。"),
    MessagesPlaceholder("history"),
    ("user", "请给我写一首孟浩然的唐诗"),
])

# 历史消息(可以动态传入)
history_data = [
    ("user", "请给我写一首李白的唐诗"),
    ("assistant", "床前明月光,疑似地上霜。举头望明月,低头思故乡"),
    ("user", "好诗再来一首"),
    ("assistant", "窗含西岭千秋雪,门泊东吴万里船"),
]

# 初始化模型
model = ChatDeepSeek(
    model_name="deepseek-chat",
    api_key="your-api-key",      # 建议从环境变量读取
    api_base="https://api.deepseek.com/v1",
    temperature=0.5,
    max_tokens=1024,
    top_p=1
)

# 构建链
chain = chat_prompt | model

# 执行链
result = chain.invoke({"history": history_data})
print(result.content)   # AIMessage 对象,用 .content 获取文本

2.3 输出解析器:StrOutputParser

模型返回的是 AIMessage 对象,若只需纯文本内容,可以添加 StrOutputParser 自动提取 .content。

python 复制代码
from langchain_core.output_parsers import StrOutputParser

chain = chat_prompt | model | StrOutputParser()
result = await chain.invoke({"history": history_data})
print(result)  # 直接输出字符串

2.4 完整 FastAPI 示例

以下是一个结合 FastAPI 的异步接口示例,注意 实际生产环境建议使用 ainvoke 以避免阻塞事件循环

python 复制代码
from fastapi import FastAPI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.output_parsers import StrOutputParser
from langchain_deepseek import ChatDeepSeek
import config_data as config

app = FastAPI()

# 全局定义提示词模板(避免每次请求重新创建)
 prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一位边塞诗人,可以作诗。"),
    MessagesPlaceholder("history"),
    ("user", "请给我写一首孟浩然的唐诗"),
])

# 全局模型实例
 model = ChatDeepSeek(
    model_name=config.DEEPSEEK_MODEL,
    api_key=config.DEEPSEEK_API_KEY,
    api_base=config.DEEPSEEK_API_URL,
    temperature=0.5,
    max_tokens=1024,
    top_p=1
)

# 链(包含输出解析器)
base_chain = prompt | model | StrOutputParser()

@app.post("/chat")
async def chat():
    # 历史数据在实际应用中应从请求参数或会话存储中获取
    history_data = [
        ("user", "请给我写一首李白的唐诗"),
        ("assistant", "床前明月光,疑似地上霜。举头望明月,低头思故乡"),
        ("user", "好诗再来一首"),
        ("assistant", "窗含西岭千秋雪,门泊东吴万里船"),
    ]
    # 调用链(注意:invoke 是同步方法,在 async 函数中建议使用 ainvoke)
    result =await base_chain.invoke({"history": history_data})
    return {"message": result}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("main2:app", host="127.0.0.1", port=8001, reload=True)

3. JsonOutputParser:将模型输出解析为字典

3.1 基本概念

JsonOutputParser 是 LangChain 内置的输出解析器,用于将模型返回的 JSON 字符串解析为 Python 字典dict)。它要求模型输出的内容是一个可被 json.loads() 正确解析的合法 JSON 字符串。

  • 输入:AIMessage(模型的原始输出)
  • 输出:dict(解析后的 JSON 对象)

使用场景:结构化数据提取、API 参数生成、多步链中的中间结果传递等。

3.2 基础用法

python 复制代码
from fastapi import FastAPI
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.output_parsers import StrOutputParser
from langchain_deepseek import ChatDeepSeek
import config_data as config
app = FastAPI()
str_parser=StrOutputParser()
json_parser=JsonOutputParser()
@app.post("/chat")
async def chat():
    first_prompt=PromptTemplate.from_template(
        "我邻居姓:{lastname},刚刚出生了{gender},请起名字,并封装到JSON格式返回,"
        "请将结果封装为JSON格式,要求key是name,value就是你起的名字,请严格遵守格式"
    ) 
    second_prompt = PromptTemplate.from_template("姓名{name},请帮我解析含义")
    model = ChatDeepSeek(
        model_name=config.DEEPSEEK_MODEL,        # 例如 "deepseek-chat"
        api_key=config.DEEPSEEK_API_KEY,    # 注意是 api_key,不是 dashscope_api_key
        api_base=config.DEEPSEEK_API_URL, 
        temperature=0.5,
        max_tokens=1024,
        top_p=1
    )
  
    chain =first_prompt | model | json_parser|second_prompt |model | str_parser
    result = chain.invoke({"lastname":"张","gender":"男"})
    return {"message":result}
    
   
if __name__ == '__main__':
    import uvicorn
    uvicorn.run("main2:app",host="127.0.0.1",port=8001,
                reload=True) 

4. 多模型链式调用与 RunnableLambda

4.1 多模型链的概念

LangChain 支持将多个模型调用串联成一个整体链。典型场景:

  1. 第一次模型调用:根据输入生成一些结构化数据(如 JSON)。
  2. 中间处理:解析第一次的输出,提取关键字段。
  3. 第二次模型调用:基于提取的字段继续执行新任务(如分析、扩展、翻译等)。

这种模式可以构建更复杂的应用,例如"起名 + 解析名字含义"、"信息抽取 + 文案生成"等。

4.2 链的基本结构

python 复制代码
chain = first_prompt | model | parser_or_lambda | second_prompt | model | str_parser
  • first_prompt:第一次调用使用的提示词模板。
  • model:语言模型(可以是同一个实例,也可以是不同模型)。
  • parser_or_lambda:将第一个模型的 AIMessage 输出转换为第二个提示词所需的 dict 参数。
  • second_prompt:第二次调用使用的提示词模板。
  • str_parser:最终将第二次模型输出的 AIMessage 转为字符串。

4.3 RunnableLambda:将任意函数转换为 Runnable

RunnableLambda 是 LangChain 提供的适配器,可以将普通函数或 lambda 表达式包装成 Runnable 对象,从而无缝插入链中。

4.3.1 语法与用法

python 复制代码
from langchain_core.runnables import RunnableLambda

 my_fun=RunnableLambda(lambda ai_msg:{"name": json.loads(ai_msg.content.strip()["name"])})

输入与输出:

  • 输入:上游组件传来的任何对象(通常是 AIMessage、dict 或 str)。
  • 输出:函数返回的值(可以是 dict、str 或任意可被下游提示词模板接受的对象)。

4.4 完整示例:两次模型调用 -- "起名 + 解析含义"

场景描述

  • 第一次调用:根据姓氏和性别生成一个名字,并以 JSON 格式返回({"name": "某某"})。
  • 提取 JSON 中的 name 字段。
  • 第二次调用:解析这个名字的含义。
python 复制代码
from fastapi import FastAPI
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_deepseek import ChatDeepSeek
from langchain_core.runnables import RunnableLambda

import config_data as config
import json
app = FastAPI()

# 最终输出解析器
str_parser = StrOutputParser()

# 初始化模型(共用同一实例)
model = ChatDeepSeek(
    model_name=config.DEEPSEEK_MODEL,
    api_key=config.DEEPSEEK_API_KEY,
    api_base=config.DEEPSEEK_API_URL,
    temperature=0.5,
    max_tokens=1024,
    top_p=1
)

@app.post("/chat")
async def chat():
    # 第一步:起名提示词(要求输出 JSON)
    first_prompt = PromptTemplate.from_template(
        "我邻居姓:{lastname},刚刚出生了{gender},请起一个名字。"
        "请将结果封装为JSON格式,要求key是name,value就是你起的名字,严格遵守格式,只输出JSON。"
    )
    
    # 第二步:解析含义提示词(使用第一次解析出的 name)
    second_prompt = PromptTemplate.from_template( "请解析名字"{name}"的含义,用中文简要说明。" )
    
    my_fun=RunnableLambda(lambda ai_msg:{"name": json.loads(ai_msg.content.strip()["name"])})
    chain = ( first_prompt| model |  my_fun| second_prompt | model| str_parser )
    result = chain.invoke({"lastname":"张","gender":"男"})
    return {"message":result}
    
    
if __name__ == '__main__':
    import uvicorn
    uvicorn.run("main2:app",host="127.0.0.1",port=8001,
                reload=True)  
    

5. 向量数据库(Chroma)

5.1 安装向量数据库

python 复制代码
pip install langchain-chroma

5.2 用法

1.什么是嵌入模型?

嵌入模型是把文本转换为向量的模型
2.使用

python 复制代码
from langchain_chroma import Chroma
from langchain_core.documents import Document
# 1. 创建向量库
vector_store = Chroma(
    collection_name="yourCollectionName",
    embedding_function=embedding,
    persist_directory="./chroma" 
)

# 2. 添加文档(Document对象)
doc_list_1 = [
    Document(page_content="苹果是一种水果", metadata={"category": "food"}),
    Document(page_content="iPhone是苹果公司的产品", metadata={"category": "tech"}),
    Document(page_content="牛顿被苹果砸中", metadata={"category": "history"}),
]
vector_store.add_documents(doc_list_1)

# 3. 使用 add_texts
vector_store.add_texts(
    texts=["春眠不觉晓"],                    # 字符串列表
    metadatas=[{"operator": "wcy"}]         #  字典列表
)

# 4. 相似度检索
results = vector_store.similarity_search(query="苹果", k=1)
for doc in results:
    print(f"* {doc.page_content} [{doc.metadata}]")

# 5. MMR检索器
retriever = vector_store.as_retriever(
    search_type="mmr",
    search_kwargs={"k": 1, "fetch_k": 2, "lambda_mult": 0.5},
)
# 执行查询并打印结果
mmr_results = retriever.invoke("thud")
print("MMR检索结果:")
for doc in mmr_results:
    print(f"- {doc.page_content} [{doc.metadata}]")

5.3 关键说明

方法/属性 作用
Chroma(embedding_function) 初始化向量库。persist_directory 指定磁盘存储路径,不设置则仅内存。
add_documents(docs) 添加 Document 对象列表(每个对象包含 page_content 和 metadata)。
add_texts(texts, metadatas) 直接添加文本列表,metadatas 为可选元数据列表,长度需与 texts 一致。
similarity_search(query,k) 返回与查询最相似的 k 个文档(无分数)。
similarity_search_with_score 返回 (Document, score) 列表,分数越小越相似(通常为欧氏距离或余弦距离)。
as_retriever(search_type) 将向量库包装为检索器(Runnable 接口),支持 similarity 或 mmr 检索类型。
search_kwargs MMR 参数:k 最终返回数,fetch_k 初始检索数,lambda_mult 相关性 vs 多样性(0~1)。

6. 数据分割

RecursiveCharacterTextSplitter 是处理通用文本时官方推荐的首选分割器。它采用递归方式尝试不同分隔符,力求在不破坏语义结构的前提下将文本分割成合适大小的块。

python 复制代码
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 配置分割器,设置块大小和重叠量
splitter = RecursiveCharacterTextSplitter(
    chunk_size=150,       # 目标块大小
    chunk_overlap=20,     # 重叠部分
    separators=["\n\n", "\n", "。", "!", "?", ";", " ", ""]
)

# 待分割的长文本
long_text = """
这是第一段落。它包含了多个句子。我们希望能保持它的结构。

这是第二段落的开始。这段文字比较长,可能会触发更细粒度的分割。
"""

# 执行分割,返回字符串列表
chunks = splitter.split_text(long_text)

# 如果你处理的是 LangChain 的文档对象列表
# docs = splitter.split_documents(documents)

7.Memory

7.1Memory 临时会话

1. 短期记忆(Session-based Memory)

  • **定义:**在一次会话(session)内,模型能记住用户之前说过的话,实现多轮对话的上下文连贯。
  • **实现方式:**通过 RunnableWithMessageHistory 包装原始链,并为每个 session_id 维护独立的 BaseChatMessageHistory 对象(这里用了 InMemoryChatMessageHistory)。

2. RunnableWithMessageHistory

  • 作用:给普通的 LCEL 链(Runnable)增加对话历史管理能力。
  • 关键参数:
  • runnable:原始链(如 prompt | model | parser)
  • get_session_history:一个可调用对象,接收 session_id: str,返回 BaseChatMessageHistory 实例
  • input_messages_key:输入字典中用户当前问题的键名(例如 "input")
  • history_messages_key:输入字典中历史消息占位符的键名(需与 MessagesPlaceholder 变量名一致)
  1. 工作流程:
  • 调用 conversation.invoke({"input": "xxx"}, config={"configurable": {"session_id": "123"}})
  • 根据 session_id 获取对应的历史存储对象
  • 从存储对象中读取历史消息列表
  • 将历史消息插入到提示词的 MessagesPlaceholder 位置
  • 构造完整输入(历史 + 当前用户消息)调用原始链
  • 将新产生的 AIMessage 追加到历史存储中

4.基础代码:

python 复制代码
"""

短期记忆:
    当前对话的短期会话 一次会话中的多轮短期会话
"""
from fastapi import FastAPI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory, InMemoryChatMessageHistory
from langchain_deepseek import ChatDeepSeek
from config_data import config
from langchain_core.output_parsers import StrOutputParser
app = FastAPI()
class  SessionHistoryManager:
    def __init__(self):
        self.store = {}
    def get_session_history(self, session_id: str) -> BaseChatMessageHistory:
        if session_id not in self.store:
            self.store[session_id] = InMemoryChatMessageHistory()
        return self.store[session_id]

history_manager = SessionHistoryManager()
# 提示词模板
prompts=ChatPromptTemplate.from_messages([
   ("system", "你需要根据会话历史回答用户问题。"),
    MessagesPlaceholder(variable_name="chat_history"),  # 关键:占位符用于插入历史消息
    ("user", "请回答用户提问:{input}")
])
models=ChatDeepSeek(
    model_name=config.DEEPSEEK_MODEL,
    api_key=config.DEEPSEEK_API_KEY,
    api_base=config.DEEPSEEK_API_URL,
    temperature=0.5,
    max_tokens=1024,
    top_p=1
)
base_chain= prompts| models | StrOutputParser()
conversation=RunnableWithMessageHistory(
    base_chain,
    history_manager.get_session_history,  # 传入方法,不是实例
    input_messages_key="input",       
    history_messages_key="chat_history" 
)

@app.post("/chat")
async def chat(input: str, session_id: str):
    try:
        result = await conversation.ainvoke(   # 使用 ainvoke
            {"input": input},
            config={"configurable": {"session_id": session_id}}
        )
        return {"response": result}
    except Exception as e:
        return {"error": str(e)}

if __name__ == '__main__':
    print("starting server...")
    import uvicorn
    uvicorn.run(app, host='0.0.0.0', port=8000)

7.2 长期会话

8.LangchainV1.下与V0.3 比较

8.1统一Agent创建接口 create_agent()

LLM智能体循环运行各种工具实现目标。智能体持续运行,知道满足条件为止(即模型发出最终输出或达到迭代次数限制)

create_anget提供生成环境的代理实现,使用langGraph构建基于图的代理运行时

python 复制代码
from langchain.agents import create_agent
create_agent(
"模型",
tools=tools
)

8.2 中间件系统(Middleware)

什么是中间件

是一种流程控制机制,用于智能体执行过程中拦截,修改或增强请求与响应的处理逻辑,而无需修改核心Agent或工具的代码

能做什么

监视器、控制、执行、调整等

中间件举例

总结摘要中间件(上下文压缩):当竭尽会话次数上限时,自动汇总对话历史记录

python 复制代码
agent=create_agent(
model='',
tools=tools,
SummarizationMiddleware(
	model='',
)
)

1.内置中间件

2.自定义中间件

自定义中间件:通过在代理执行流程的特定点运行狗子来构建自定义中间件

基于装饰器的:适用于单钩中间件的快速简便

基于类的:对于具有多个钩子的复杂中间件来说功能更强大

8.2.3 自定义中间件

8.2.3.1 围绕模型-修饰器

python 复制代码
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
from langchain.agents.middleware import wrap_model_call,ModelRequest,ModelResponse
from langgraph.checkpoint.memory import InMemorySaver  
from typing import Callable
base_model = ChatOpenAI(temperature=0, model="gpt-3.5-turbo")  # 基础模型
model = ChatOpenAI(temperature=0, model="gpt-4")  # 高级模型

#围绕每次模型调用 如果请求大于5次 切换模型
@wrap_model_call
def switch_model(request:ModelRequest,handler:Callable[[ModelRequest],ModelResponse])->ModelResponse:
    model=base_model
    """根据对话轮次动态选择模型"""
    message_count = len(request.state["messages"])
    if message_count > 10:
        print("检测到长对话切换模型")
        return handler(request.override(model=model))
    else:
        return handler(request)

agents=create_agent(
    model=base_model,
    tools=[],
    middleware=[switch_model],
    checkpointer=InMemorySaver(),
)
config={"configurable":{"thread_id":"1111"}}
chunks=agents.stream({"messages":[{'role':'user','content':'hello word'}]},config=config)
for chunk in chunks:
    print(chunk)

8.2.3.2 围绕模型-类

python 复制代码
from langchain.agents import create_agent
from langchain_deepseek import ChatDeepSeek
from langgraph.checkpoint.memory import InMemorySaver  
from langchain.agents.middleware import AgentMiddleware ,ModelRequest,ModelResponse
from langchain_openai import ChatOpenAI
from typing import Callable

base_model = ChatOpenAI(temperature=0, model="gpt-3.5-turbo")  # 基础模型
model = ChatDeepSeek(temperature=0,  model="deepseek-chat")  # 高级模型

class SwitchModel(AgentMiddleware):
    def __init__(self, model: Callable, base_model: Callable):
        super().__init__()
        self.model = model
        self.base_model = base_model
    def wrap_model_call(
        self, 
        request: ModelRequest, 
        handler: Callable[[ModelRequest], ModelResponse]
    ) -> ModelResponse:
        message_count = len(request.state["messages"])  # 注意是 request.state["messages"]
        if message_count > 10:
            print(f"切换到高级模型(消息数: {message_count})")
            return handler(request.override(model=self.model))
        else:
            print(f"使用基础模型(消息数: {message_count})")
            return handler(request)


switchModel = SwitchModel(model, base_model)
agent =create_agent(
    model=base_model,
    tools=[],
    middleware=[switchModel],
    checkpointer=InMemorySaver(),
)
# 添加短期记忆功能
config={"configurable":{"thread_id":"1111"}}
chunks=agent.stream(
    {"messages":[{'role':'user','content':'hello word'}]},
    config=config
)

3.标准输出

4.结构化输出

8.3 Langchain是一个构建LLM应用的核心框架

9.Langchin 实现RAG(检索增强生成)

1.索引化

将整个文档进行切块(完整/语义)------->将切块成文档嵌入模型---->进行索引化--》文档+向量+id+元数据

2.检索、查询

query--->Encode---问题向量化-->去向量数据库查询->返回结果-->加入提示词|大模型进行查询------>返回结果

#10 召回

召回:其实就是去向量数据库进行检索,

检索的过程:召回->精排->生成

10.1 多路召回概述

多路召回概述

多路召回是结合多种召回策略的结果,如向量 召回基于语义相似度,关键词 召回基于传统匹配算法,融合多路结果得到更全面准确的候选文档集合,
重要性:

在RAG架构中,多路召回能够提高信息检索的效率和准确性,为后续的生产环境提供更丰富的上下文信息,从而生成更高质量的回答
应用场景

广泛引用与搜索引擎、推荐系统】智能客服等领域、尤其在医疗、金融等对信息准确性要求较高的领域,多路召回能够更好地满足用户需求

多路召回方式
并行多路召回:将不同召回策略的结果分别获取进行合并去重,在通过重排序综合打分 ,综合打分,去最终的Top N结果。例如向量召回Top 10,,BM25文本召回Top 10,合并后重排序取Top10
优势:充分
利用语义和关键词
两种优势,互补性强,能够更全面的覆盖候选文档,减少因单一招呼策略导致落检问题,是当前工业界最流行的做法
串行多路召回

实现方式:

串行召回是先用一路召回大量粗筛结果,在用另一路算发粗筛结果做精排。

例如先用向量召回100条,再用BM25重新打分排序取Top 10. 页可以反过来操作

适用场景

当数据量较大且计算资源有限时,串行多路召回可以有效减少计算量,先通过粗筛快速缩小范围,再通过精排提高结果质量。

优缺点

优点是计算效率较高,缺点是如果粗筛阶段筛选不准确,可能会导致后续精排阶段丢失重要信息,影响最终结果的准确性。

相关推荐
xingyuzhisuan1 小时前
从零精通GPU服务器模型部署:标准化流程与性能调优实战
运维·服务器·人工智能
一起聊电气1 小时前
告别盲目制冷!AI空调自控,让建筑自主呼吸、按需耗能
人工智能
问心无愧05131 小时前
ctf show web入门257
android·前端·笔记
java1234_小锋1 小时前
什么是 RAG(检索增强生成)?请简述 Spring AI 实现 RAG 的完整流程,包括涉及的核心组件。
java·人工智能·spring·rag
小真zzz1 小时前
9.8分登顶:搜极星如何以绝对中立与专业,定义AI时代品牌洞察新范式
大数据·人工智能·搜索引擎·ai
weixin_397574091 小时前
Agent推理可视化打破AI黑盒,让思考过程透明可见
人工智能
Saniffer_SH1 小时前
【每日一题】不只是点亮画面:UniGraf 如何把 HDMI/DP 接口问题拆成可定位、可复现、可自动化验证的测试流程?
运维·人工智能·测试工具·fpga开发·性能优化·自动化·压力测试
ai产品老杨1 小时前
解耦异构算力与多协议接入:基于 Docker 与 GB28181 的企业级 AI 视频管理平台架构演进与源码交付实践
人工智能·docker·音视频
郑寿昌1 小时前
2026 全球 AI 工厂市场格局与发展趋势
大数据·人工智能·microsoft