找回密码
 立即注册
首页 业界区 业界 LangChain框架入门07:AI应用监控神器LangSmith ...

LangChain框架入门07:AI应用监控神器LangSmith

湄圳啸 5 小时前
在上一篇文章中,我们介绍了LCEL表达式和Runnable组件,通过LCEL表达式可以很轻松的构建复杂的AI应用,LCEL将多个可运行组件串联起来,在执行LCEL表达式时出现了错误,如何判断是哪个组件出现了错误?又如何获取出现错误的上下文呢?
本文将会详细介绍使用LangChain提供的Callback回调机制,如何对LLM应用以及LCEL执行的各个关键节点进行监控,最后,还会介绍LangChain推出的一款在开发阶段的调试监控神器LangSmith,只需要简单的配置就可以和LangChain构建的应用进行无缝集成,自动监控整个项目的生命周期,将监控的结果自动上传到LangSmith平台,使项目监控变得非常简单。
文中所有示例代码:https://github.com/wzycoding/langchain-study
一、什么是LangSmith

LangSmith 是一个由LangChain推出,用于构建LLM应用的监控平台,如下图所示,LangSmith的功能主要包括以下三个方面:
可观测性:LangSmith可以进行数据的分析和追踪,并提供了仪表盘、告警等功能。
可评估:可以对应用运行情况进行评估,分析其性能表现。
提示词工程:支持对提示词进行管理,并且提供提示词版本控制功能
1.png

LangSmith由LangChain提供,无需本地部署,LangSmith地址如下:
https://smith.langchain.com/
登录后界面
2.png

二、LangSmith使用

首先点击Tracing Projects
3.png

系统中默认存在一个项目,点击New Project创建新项目
4.png

LangSmith支持LangChain项目和非LangChain项目,并且分别提供了将LangSmith接入到应用的方法,点击Generate API Key,生成API Key
5.png

复制保存好API KEY,并修改项目名为langchain-study,下方的配置也会自动变成对应项目名称
6.png

复制上方配置,放到项目中的.env文件中
  1. # LangSmith配置
  2. LANGSMITH_TRACING="true"
  3. LANGSMITH_ENDPOINT="https://api.smith.langchain.com"
  4. LANGSMITH_API_KEY="lsv2_pt_***************************"
  5. LANGSMITH_PROJECT="langchain-study"
复制代码
通过一个最简单的示例进行测试:
  1. import dotenv
  2. from langchain_core.output_parsers import StrOutputParser
  3. from langchain_core.prompts import ChatPromptTemplate
  4. from langchain_openai import ChatOpenAI
  5. # 读取env配置
  6. dotenv.load_dotenv()
  7. # 1.创建提示词模板
  8. prompt = ChatPromptTemplate.from_template("{question}")
  9. # 2.构建GPT-3.5模型
  10. llm = ChatOpenAI(model="gpt-3.5-turbo")
  11. # 3.创建输出解析器
  12. parser = StrOutputParser()
  13. # 4.执行链
  14. chain = prompt | llm | parser
  15. print(chain.invoke({"question": "请以表格的形式返回三国演义实力最强的十个人,并进行简要介绍"}))
复制代码
执行完成之后,在Tracing Projects页面就可以看到langchain-study项目被成功创建
7.png

点击进入项目,就可以看到刚刚那一次的调用过程,包括输入、输出、发起时间、总耗时等信息
8.png

点击All Runs可以查看各个组件的执行过程,包括Prompt生成、LLM响应、输出解析器处理等各环节的详细执行信息

点击任意组件,如ChatPromptTemplate,就会将组件的输入和输出结果进行展示
10.png

下拉选择,选择Raw Input就可以展示原始的输入,输出部分也可以以相同方式查看原始信息
11.png

支持 JSON 与 YAML 格式展示,其中 JSON 更便于观察,如下图可以清晰的观察到ChatPromptTemplate组件的原始输入输出信息
12.png

下面我们将程序改成不存在的模型gpt-3.6-turbo,重新执行程序,来模拟出现错误的情况。
  1. llm = ChatOpenAI(model="gpt-3.6-turbo")
复制代码
在LangSmith中,可以看到执行记录和错误原因
13.png

也可以详细查看错误详细原因
14.png

三、什么是Callback机制

除了使用LangSmith之外,LangChain还提供了一种回调机制,可以在 LLM 应用程序的各种阶段执行特定的钩子方法。通过这些钩子方法,我们可以轻松地进行日志输出、异常监控等任务,Callback支持以下事件的钩子方法:
Event 事件触发时机关联钩子方法Chat model start聊天模型启动on_chat_model_startLLM start LLMLLM模型启动on_llm_startLLM new token LLMLLM生成新的 token 时触发,仅在启用流式输出(streaming)模式下生效on_llm_new_tokenLLM endsLLM 或聊天模型完成运行时on_llm_endLLM errorsLLM 或聊天模型出错on_llm_errorChain start链开始执行(实际上就是每个可运行组件开始执行)on_chain_startChain end链结束执行(实际上就是每个可运行组件结束执行)on_chain_endChain error链执行出错on_chain_errorTool start工具开始执行on_tool_startTool end工具结束执行on_tool_endTool error工具执行出错on_tool_errorAgent actionagent开始执行on_agent_actionAgent finishagent结束执行on_agent_finishRetriever start检索器开始执行on_retriever_startRetriever end检索器结束执行on_retriever_endRetriever error检索器执行出错on_retriever_errorText每次模型输出一段文本时,就会调用这个方法on_textRetry当某个组件(比如 LLM 调用或链)发生失败并触发重试机制时on_retry四、如何使用Callback机制

首先,使用Callback机制,需要使用到Callback handler,即回调处理器,那些各个生命周期的钩子方法,就定义在回调处理器中,回调处理器支持同步和异步,同步回调处理器继承BaseCallbackHandler类,异步回调处理器继承AsyncCallbackHandler类。
如下图在PyCharm中,定义类继承BaseCallbackHandler类,使用ctrl+o快捷键,就会出现这些可以重写的钩子方法。
15.png

那么,如何使自定义的CallbackHandler生效呢?可以在调用可执行组件的invoke()方法中,除了传递输入参数外,再传递config配置参数,config配置参数可以传递各种配置信息,其中,callbacks属性用来传递回调处理器,callbacks属性接收一个数组,数组里面包含自定义的CallbackHandler对象,代码示例如下:
  1. from typing import Dict, Any, Optional, List
  2. from uuid import UUID
  3. import dotenv
  4. from langchain_core.callbacks import BaseCallbackHandler
  5. from langchain_core.messages import BaseMessage
  6. from langchain_core.output_parsers import StrOutputParser
  7. from langchain_core.outputs import LLMResult
  8. from langchain_core.prompts import ChatPromptTemplate
  9. from langchain_openai import ChatOpenAI
  10. dotenv.load_dotenv()
  11. class CustomCallbackHandler(BaseCallbackHandler):
  12.     """自定义回调处理类"""
  13.     def on_chat_model_start(self, serialized: Dict[str, Any], messages: List[List[BaseMessage]], *, run_id: UUID,
  14.                             parent_run_id: Optional[UUID] = None, tags: Optional[List[str]] = None,
  15.                             metadata: Optional[Dict[str, Any]] = None, **kwargs: Any) -> Any:
  16.         print("======聊天模型结束执行======")
  17.     def on_llm_end(self, response: LLMResult, *, run_id: UUID, parent_run_id: Optional[UUID] = None,
  18.                    **kwargs: Any) -> Any:
  19.         print("======聊天模型结束执行======")
  20.     def on_chain_start(self, serialized: Dict[str, Any], inputs: Dict[str, Any], *, run_id: UUID,
  21.                        parent_run_id: Optional[UUID] = None, tags: Optional[List[str]] = None,
  22.                        metadata: Optional[Dict[str, Any]] = None, **kwargs: Any) -> Any:
  23.         print(f"开始执行当前组件{kwargs['name']},run_id: {run_id}, 入参:{inputs}")
  24.     def on_chain_end(self, outputs: Dict[str, Any], *, run_id: UUID, parent_run_id: Optional[UUID] = None,
  25.                      **kwargs: Any) -> Any:
  26.         print(f"结束执行当前组件,run_id: {run_id}, 执行结果:{outputs}, {kwargs}")
  27. # 1.创建提示词模板
  28. prompt = ChatPromptTemplate.from_template("{question}")
  29. # 2.构建GPT-3.5模型
  30. llm = ChatOpenAI(model="gpt-3.5-turbo")
  31. # 3.创建输出解析器
  32. parser = StrOutputParser()
  33. # 4.执行链
  34. chain = prompt | llm | parser
  35. chain.invoke({"question": "请输出静夜思的原文"},
  36.              {"callbacks": [CustomCallbackHandler()]})
复制代码
在示例中,创建了一个CustomCallbackHandler类,继承了BaseCallbackHandler,分别重写了on_chain_start、on_llm_end、on_chain_start、on_chain_end,在聊天模型开始执行和结束执行进行了信息输出,在on_chain_start、on_chain_end打印了当前链执行的组件名称、运行id、输入参数、输出结果。
执行结果如下,通过输出结果可以清晰地看到每一个组件的输入和输出结果,以及LLM何时开始执行、结束执行,若需监控异常情况,可重写 on_chain_error 方法。
  1. 开始执行当前组件RunnableSequence,run_id: 6eaf8cba-87d8-4e8f-8ec3-ea67a2b2cc6c, 入参:{'question': '请输出静夜思的原文'}
  2. 开始执行当前组件ChatPromptTemplate,run_id: 5f452385-74e3-40bf-a7b7-2dcbb921b801, 入参:{'question': '请输出静夜思的原文'}
  3. 结束执行当前组件,run_id: 5f452385-74e3-40bf-a7b7-2dcbb921b801, 执行结果:messages=[HumanMessage(content='请输出静夜思的原文')], {'tags': ['seq:step:1']}
  4. ======聊天模型结束执行======
  5. ======聊天模型结束执行======
  6. 开始执行当前组件StrOutputParser,run_id: 7c1043c0-aa7c-4969-9822-f8464b312922, 入参:content='《静夜思》是唐代诗人李白创作的一首诗,原文如下:\n\n**静夜思**\n\n床前明月光,  \n疑是地上霜。  \n举头望明月,  \n低头思故乡。' response_metadata={'token_usage': {'completion_tokens': 76, 'prompt_tokens': 17, 'total_tokens': 93, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_b28b39ffa8', 'finish_reason': 'stop', 'logprobs': None} id='run-80f91d8a-c8d0-47c5-8255-806272bdbfcf-0' usage_metadata={'input_tokens': 17, 'output_tokens': 76, 'total_tokens': 93}
  7. 结束执行当前组件,run_id: 7c1043c0-aa7c-4969-9822-f8464b312922, 执行结果:《静夜思》是唐代诗人李白创作的一首诗,原文如下:
  8. **静夜思**
  9. 床前明月光,  
  10. 疑是地上霜。  
  11. 举头望明月,  
  12. 低头思故乡。, {'tags': ['seq:step:3']}
  13. 结束执行当前组件,run_id: 6eaf8cba-87d8-4e8f-8ec3-ea67a2b2cc6c, 执行结果:《静夜思》是唐代诗人李白创作的一首诗,原文如下:
  14. **静夜思**
  15. 床前明月光,  
  16. 疑是地上霜。  
  17. 举头望明月,  
  18. 低头思故乡。, {'tags': []}
复制代码
五、总结

本文介绍了什么是LangSmith,以及如何创建LangSmith应用、无缝集成到LangChain当中,通过LangSmith可以清晰的监控到AI应用每一步的执行过程,包括执行时间、原始输入输出、花费金额、使用token数等详细信息。
随后我们还介绍了LangChain提供的Callback机制,利用BaseCallbackHandler提供的钩子方法,可以轻松地监控各个关键执行流程,有读者可能会疑惑:既然有了 LangSmith,为何还需要 Callback 机制?在实际开发中,LangSmith 更适合在开发调试阶段使用,而在生产环境下,出于数据隐私和安全考量,我们通常不会将敏感数据上传到LangSmith平台。这时,Callback 机制就能将执行信息接入到本地或自定义的监控系统,实现同样的可观测性。
相信通过本文你已经掌握如何对AI应用进行监控,后续将继续深入介绍LangChain的核心模块和高级用法,敬请期待。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册