LangChain 26: 回调函数callbacks打印prompt verbose调用

本文介绍了LangChain库中的回调系统,包括CallbackHandlers接口、构造函数回调和请求回调的使用场景,以及如何通过回调进行日志记录、监控和流式传输等操作的实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LangChain系列文章

  1. LangChain 实现给动物取名字
  2. LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字
  3. LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄
  4. LangChain 4用向量数据库Faiss存储,读取YouTube的视频文本搜索Indexes for information retrieve
  5. LangChain 5易速鲜花内部问答系统
  6. LangChain 6根据图片生成推广文案HuggingFace中的image-caption模型
  7. LangChain 7 文本模型TextLangChain和聊天模型ChatLangChain
  8. LangChain 8 模型Model I/O:输入提示、调用模型、解析输出
  9. LangChain 9 模型Model I/O 聊天提示词ChatPromptTemplate, 少量样本提示词FewShotPrompt
  10. LangChain 10思维链Chain of Thought一步一步的思考 think step by step
  11. LangChain 11实现思维树Implementing the Tree of Thoughts in LangChain’s Chain
  12. LangChain 12调用模型HuggingFace中的Llama2和Google Flan t5
  13. LangChain 13输出解析Output Parsers 自动修复解析器
  14. LangChain 14 SequencialChain链接不同的组件
  15. LangChain 15根据问题自动路由Router Chain确定用户的意图
  16. LangChain 16 通过Memory记住历史对话的内容
  17. LangChain 17 LangSmith调试、测试、评估和监视基于任何LLM框架构建的链和智能代理
  18. LangChain 18 LangSmith监控评估Agent并创建对应的数据库
  19. LangChain 19 Agents Reason+Action自定义agent处理OpenAI的计算缺陷
  20. LangChain 20 Agents调用google搜索API搜索市场价格 Reason Action:在语言模型中协同推理和行动
  21. LangChain 21 Agents自问自答与搜索 Self-ask with search
  22. LangChain 22 LangServe用于一键部署LangChain应用程序
  23. LangChain 23 Agents中的Tools用于增强和扩展智能代理agent的功能
  24. LangChain 24 对本地文档的搜索RAG检索增强生成Retrieval-augmented generation
  25. LangChain 25: SQL Agent通过自然语言查询数据库sqlite
    在这里插入图片描述

1. 回调Callbacks

LangChain提供了一个回调系统,允许您钩入LLM应用程序的各个阶段。这对于记录、监控、流式传输和其他任务非常有用。

您可以通过使用API中的callbacks参数订阅这些事件。这个参数是处理程序对象的列表,这些对象预期实现下面更详细描述的一个或多个方法。

2. Callback handlers 回调处理程序

CallbackHandlers是实现CallbackHandler接口的对象,该接口针对可以订阅的每个事件都有一个方法。当事件触发时,CallbackManager将在每个处理程序上调用适当的方法。

class BaseCallbackHandler:
    """Base callback handler that can be used to handle callbacks from langchain."""

    def on_llm_start(
        self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any
    ) -> Any:
        """Run when LLM starts running."""

    def on_chat_model_start(
        self, serialized: Dict[str, Any], messages: List[List[BaseMessage]], **kwargs: Any
    ) -> Any:
        """Run when Chat Model starts running."""

    def on_llm_new_token(self, token: str, **kwargs: Any) -> Any:
        """Run on new LLM token. Only available when streaming is enabled."""

    def on_llm_end(self, response: LLMResult, **kwargs: Any) -> Any:
        """Run when LLM ends running."""

    def on_llm_error(
        self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
    ) -> Any:
        """Run when LLM errors."""

    def on_chain_start(
        self, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs: Any
    ) -> Any:
        """Run when chain starts running."""

    def on_chain_end(self, outputs: Dict[str, Any], **kwargs: Any) -> Any:
        """Run when chain ends running."""

    def on_chain_error(
        self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
    ) -> Any:
        """Run when chain errors."""

    def on_tool_start(
        self, serialized: Dict[str, Any], input_str: str, **kwargs: Any
    ) -> Any:
        """Run when tool starts running."""

    def on_tool_end(self, output: str, **kwargs: Any) -> Any:
        """Run when tool ends running."""

    def on_tool_error(
        self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
    ) -> Any:
        """Run when tool errors."""

    def on_text(self, text: str, **kwargs: Any) -> Any:
        """Run on arbitrary text."""

    def on_agent_action(self, action: AgentAction, **kwargs: Any) -> Any:
        """Run on agent action."""

    def on_agent_finish(self, finish: AgentFinish, **kwargs: Any) -> Any:
        """Run on agent end."""

3. 回调函数的使用场景

回调函数参数可用于 API 中的大多数对象(链、模型、工具、代理等),分别有两个不同的使用场景:

  • 构造函数回调函数:在构造函数中定义,例如 LLMChain(callbacks=[handler], tags=['a-tag']),将用于该对象上的所有调用,并且仅限于该对象,例如如果您将处理程序传递给 LLMChain 构造函数,则不会被附加到该链上的模型使用。

  • 请求回调函数:在 run()/apply() 方法中定义,用于发出请求,例如 chain.run(input, callbacks=[handler]),将仅用于该特定请求以及其中包含的所有子请求(例如对LLMChain的调用触发对模型的调用,该模型使用在 call() 方法中传递的相同处理程序)。

verbose 参数可用于 API 中的大多数对象(链、模型、工具、代理等)作为构造函数参数,例如 LLMChain(verbose=True),相当于将 ConsoleCallbackHandler 传递给该对象和所有子对象的回调参数。这对于调试非常有用,因为它将所有事件记录到控制台。

4. 你想要在什么时候使用这些回调函数呢?

  • 构造函数回调最适用于诸如日志记录、监控等用例,这些用例并不特定于单个请求,而是整个链条。例如,如果你想要记录发送到LLMChain的所有请求,你可以将一个处理程序传递给构造函数。

  • 请求回调最适用于诸如流式传输等用例,其中你想要将单个请求的输出流传输到特定的websocket连接,或者其他类似的用例。例如,如果你想要将单个请求的输出流传输到websocket,你可以将一个处理程序传递给call()方法。

5. 代码实现

LangChain提供了一些内置处理程序,您可以使用它们来开始。这些都可以在langchain/callbacks模块中找到。最基本的处理程序是StdOutCallbackHandler,它只是将所有事件记录到标准输出。

注意:当对象上的verbose标志设置为true时,即使没有显式传递,StdOutCallbackHandler也会被调用。

from langchain.callbacks import StdOutCallbackHandler
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate

handler = StdOutCallbackHandler()
llm = OpenAI()
prompt = PromptTemplate.from_template("1 + {number} = ")

# Constructor callback: First, let's explicitly set the StdOutCallbackHandler when initializing our chain
chain = LLMChain(llm=llm, prompt=prompt, callbacks=[handler])
chain.run(number=2)

# Use verbose flag: Then, let's use the `verbose` flag to achieve the same result
chain = LLMChain(llm=llm, prompt=prompt, verbose=True)
chain.run(number=2)

# Request callbacks: Finally, let's use the request `callbacks` to achieve the same result
chain = LLMChain(llm=llm, prompt=prompt)
chain.run(number=2, callbacks=[handler])

运行结果

langchain-llm-app (develop*) » python Callbacks/llm_callbacks.py         ~/Workspace/LLM/langchain-llm-app 1> Entering new LLMChain chain...
Prompt after formatting:
1 + 2 = 

> Finished chain.


> Entering new LLMChain chain...
Prompt after formatting:
1 + 2 = 

> Finished chain.


> Entering new LLMChain chain...
Prompt after formatting:
1 + 2 = 

> Finished chain.

代码

https://github.com/zgpeace/pets-name-langchain/tree/develop

参考

https://python.langchain.com/docs/modules/callbacks/

<think>嗯,用户的问题是关于当大模型返回空结果时,如何让系统自己回答问题。他们提供了一段使用GraphCypherQAChain的代码,涉及两个不同的模型:qa_llm和cypher_llm。首先,我需要理解代码的结构和各个部分的作用。 看起来用户在使用LangChain框架,特别是GraphCypherQAChain。这个链的作用可能是先通过cypher_llm生成Cypher查询,然后执行查询得到结果,最后用qa_llm生成回答。问题出现在当查询结果为空时,链可能直接返回空,而不继续调用qa_llm。这时候需要修改逻辑,使得即使结果为空,qa_llm也能处理这种情况,生成友好的回复。 首先,我需要确认GraphCypherQAChain的工作流程。通常,这类链会先生成查询,执行查询,然后根据结果生成回答。如果查询结果为空,可能默认不调用qa_llm。所以需要找到在结果为空时触发qa_llm的方法。 可能的解决方案包括自定义处理逻辑,比如继承或修改GraphCypherQAChain的_call方法,在结果为空时主动调用qa_llm。或者,检查现有的参数是否有相关设置,比如错误处理或回退机制。另外,可能需要处理返回结构,确保空结果也能传递到qa_llm。 然后,考虑到用户提供的代码中使用了validate_cypher和verbose等参数,可能需要在这些设置之外添加自定义逻辑。例如,在生成Cypher查询后,检查结果是否为空,如果为空,则构造一个默认提示,让qa_llm生成回复,比如“没有找到相关信息”。 另外,可能需要在链的配置中添加错误处理或空结果处理的回调函数。或者,在生成回答的阶段,判断输入是否为空,并做相应处理。可能需要查阅LangChain的文档,特别是GraphCypherQAChain的源码,看看是否有可以覆盖的方法或可用的钩子。 如果GraphCypherQAChain没有直接支持这种处理的参数,那么自定义一个子类可能是必要的。覆盖其执行查询和生成回答的方法,在结果为空时,手动调用qa_llm,并传入特定的提示,如“当前查询无数据,请根据知识库回答”。 同时,需要注意异常处理,确保在查询执行失败或返回空时,流程能正确转向调用qa_llm。此外,保持原有的参数如validate_cypher和verbose的功能,避免影响现有逻辑。 可能的实现步骤: 1. 创建GraphCypherQAChain的子类。 2. 重写相关方法(如_call或生成回答的方法),在结果为空时触发qa_llm。 3. 在触发时构造适当的提示,让qa_llm返回友好的信息。 4. 测试修改后的链,确保在空结果时能正确响应。 另外,可能需要处理不同的空结果情况,比如查询本身有误导致无结果,或者确实没有数据。这时候可能需要区分情况,但用户当前需求可能只需要统一处理为空的情况。 最后,确保代码修改后的兼容性和稳定性,尤其是在生产环境中。使用allow_dangerous_requests=True可能涉及安全设置,需要确认修改后的代码不会引入新的问题。</think>在LangChain框架的`GraphCypherQAChain`中,当Cypher查询结果为空时,可以通过以下方案实现大模型自主回答: ### 问题分析 代码中现有逻辑的缺陷是: 1. 当Cypher查询返回空结果时,流程直接终止 2. 未触发`qa_llm`进行兜底回答 3. 缺少对空结果的特殊处理逻辑 ### 解决方案 通过**自定义处理逻辑**实现空结果兜底机制: ```python from langchain.chains.graph_qa.cypher_utils import CypherQueryCorrector, Schema from langchain_core.runnables import RunnablePassthrough from langchain_core.prompts import ChatPromptTemplate class CustomGraphCypherQAChain(GraphCypherQAChain): def _call(self, inputs): try: # 原始查询逻辑 generated_cypher = self.cypher_generation_chain.run( inputs["question"], callbacks=self.callbacks ) # 执行Cypher查询 context = self.graph.query(generated_cypher) # 空结果处理 if not context: # 构造兜底提示 empty_prompt = "当前知识库未找到相关数据,请根据你的通用知识回答:{question}" return self.qa_llm.invoke(empty_prompt.format(question=inputs["question"])) # 正常结果处理 return self.qa_chain.invoke( {"question": inputs["question"], "context": context}, callbacks=self.callbacks, ) except Exception as e: # 异常兜底 error_prompt = f"查询执行失败(错误:{str(e)}),请自行回答问题:{inputs['question']}" return self.qa_llm.invoke(error_prompt) ``` ### 改造后的调用方式 ```python def build_custom_chain(): # 保持原有模型配置不变 qa_llm = ChatOllama(...) cypher_llm = ChatOpenAI(...) return CustomGraphCypherQAChain.from_llm( graph=graph, cypher_llm=cypher_llm, qa_llm=qa_llm, validate_cypher=True, verbose=True, allow_dangerous_requests=True ) ``` ### 关键改进点说明 1. **空结果检测** 通过`if not context:`判断查询结果是否为空,触发兜底逻辑 2. **分级处理策略** - 一级兜底:空结果时使用特定prompt要求LLM自主回答 - 二级兜底:异常捕获后强制LLM回答问题 3. **提示工程优化** 定制专用提示模板: ```python empty_prompt = "当前知识库未找到相关数据,请根据你的通用知识回答:{question}" error_prompt = f"查询执行失败(错误:{str(e)}),请自行回答问题:{inputs['question']}" ``` ### 效果验证 | 场景类型 | 原逻辑表现 | 改进后表现 | |----------------|------------|----------------------| | 正常查询结果 | 返回答案 | 正常返回知识库答案 | | 空查询结果 | 无响应 | 返回LLM通用知识答案 | | Cypher语法错误 | 抛出异常 | 返回LLM通用知识答案 | ### 扩展建议 1. **阈值控制**:可添加`min_results=1`参数控制最少返回结果数 2. **日志记录**:记录空结果问题用于后续知识库完善 3. **混合回答**:将知识库空结果与LLM回答组合输出 ```python if not context: llm_answer = self.qa_llm(...) return f"未找到精确匹配记录,根据通用知识推断:{llm_answer}" ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值