掘金 人工智能 05月01日 17:48
如何通过日志在本地调试LangChain编写的程序?
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了在本地调试LangChain程序时,如何查看与LLM交互的详细信息,无需登录LangSmith网站。通过LangChain的set_debug(True)可以查看基本的输入输出数据和token消耗。更进一步,通过启用全局Debug日志,可以查看HTTP请求的地址、端口、header和状态码。更高级的技巧是,利用ChatOpenAI并自定义httpx客户端,通过hook函数完整地打印HTTP请求和响应信息,从而实现更深入的调试。

✅ 使用`langchain.globals.set_debug(True)`可以在本地控制台输出LangChain程序与LLM交互的基本信息,如输入输出数据和token消耗量,无需依赖LangSmith。

🛠️ 启用全局Debug日志(`logging.basicConfig(level=logging.DEBUG)`)可以查看与后端大模型API服务的HTTP请求的地址、端口、header以及HTTP状态码等信息,帮助开发者了解网络通信状态。

📡 通过将`ChatOllama`替换为`ChatOpenAI`,并自定义`httpx.Client`,可以利用hook函数`log_request`和`log_response`完整地打印HTTP请求和响应的header和body,从而获取与LLM交互的全部细节。

⚠️ 这种查看HTTP请求和响应信息的方法依赖于`ChatOpenAI`支持传入`http_client`参数,并要求后端大模型服务兼容OpenAI的API规范,这限制了其适用范围。

LangSmith可以记录LangChain程序对LLM的调用,但它需要登陆LangSmith网站才能看到。有什么办法在本地就能看到详细的信息,以方便调试LangChain编写的程序吗?

使用LangChain提供的set_debug(True)

在Python代码中只需要导入set_debug这个方法,再调用即可。参考代码如下

from langchain_ollama import ChatOllama  from langchain.globals import set_debug    set_debug(True)  llm = ChatOllama(model="llama3:8b")  response = llm.invoke("What are you?")

这段代码访问了本地通过Ollama部署的llama3大模型,提了一个简单的问题就结束了。执行后我们可以在日志中看到如下的日志

[llm/start] [llm:ChatOllama] Entering LLM run with input:{  "prompts": [    "Human: What are you?"  ]}[llm/end] [llm:ChatOllama] [8.92s] Exiting LLM run with output:{  "generations": [    [      {        "text": "I am LLaMA, an AI assistant developed by Meta AI that can understand and respond to human input in a conversational manner. ... What would you like to talk about?",        ...        "type": "ChatGeneration",        "message": {          "lc": 1,          "type": "constructor",          "id": [            "langchain",            "schema",            "messages",            "AIMessage"          ],          "kwargs": {            ...            "usage_metadata": {              "input_tokens": 14,              "output_tokens": 116,              "total_tokens": 130            },            "tool_calls": [],            "invalid_tool_calls": []          }    ...}

这里我们能看到LangChain代码内部运行产生的输入输出数据。在输出数据中,能看到大模型返回的信息、消耗的token等信息。如果使用了LangSmith的话,你会发现这些信息和LangSmith里记录的信息差不多(不过LangSmith里还额外记录了很多元数据)。

有的时候你可能想查看更多的信息,比如程序和后端大模型API服务的http请求响应信息,需要怎么做呢?

启用全局的Debug日志

在代码里启用全局的Debug日志,代码如下

from langchain_ollama import ChatOllama  import logging  logging.basicConfig(level=logging.DEBUG)    llm = ChatOllama(model="llama3:8b")  response = llm.invoke("What are you?")

这时运行程序会看到下面的日志

DEBUG:httpcore.connection:connect_tcp.started host='127.0.0.1' port=11434 local_address=None timeout=None socket_options=NoneDEBUG:httpcore.connection:connect_tcp.complete return_value=<httpcore._backends.sync.SyncStream object at 0x11876b520>DEBUG:httpcore.http11:send_request_headers.started request=<Request [b'POST']>DEBUG:httpcore.http11:send_request_headers.completeDEBUG:httpcore.http11:send_request_body.started request=<Request [b'POST']>DEBUG:httpcore.http11:send_request_body.completeDEBUG:httpcore.http11:receive_response_headers.started request=<Request [b'POST']>DEBUG:httpcore.http11:receive_response_headers.complete return_value=(b'HTTP/1.1', 200, b'OK', [(b'Content-Type', b'application/x-ndjson'), (b'Date', b'Thu, 01 May 2025 05:59:24 GMT'), (b'Transfer-Encoding', b'chunked')])INFO:httpx:HTTP Request: POST http://127.0.0.1:11434/api/chat "HTTP/1.1 200 OK"DEBUG:httpcore.http11:receive_response_body.started request=<Request [b'POST']>DEBUG:httpcore.http11:receive_response_body.completeDEBUG:httpcore.http11:response_closed.startedDEBUG:httpcore.http11:response_closed.complete

现在能看到http请求和响应的信息了,但也只是一点点而已,只有后端服务的地址、端口、header、HTTP状态码。还能有更多的信息吗?机缘巧合下,我发现对程序稍加修改就能看到更多的信息。

from langchain_openai import ChatOpenAI  import logging  logging.basicConfig(level=logging.DEBUG)    llm = ChatOpenAI(      model="llama3:8b",      base_url="http://localhost:11434/v1",      api_key="123456"  )  response = llm.invoke("What are you?")

这里把对ChatOllama的使用改为ChatOpenAI,日志中就会多出一些openai的日志

DEBUG:openai._base_client:Request options: {'method': 'post', 'url': '/chat/completions', 'files': None, 'idempotency_key': 'stainless-python-retry-fe5f895d-c0da-4216-a273-b16f967433d3', 'json_data': {'messages': [{'content': 'What are you?', 'role': 'user'}], 'model': 'llama3:8b', 'stream': False}}DEBUG:openai._base_client:Sending HTTP Request: POST http://localhost:11434/v1/chat/completions

这里我们能看到和后端大模型服务交互的地址和HTTP request body(也就是上面json_data的值),但还是缺少HTTP response的详细信息。好在ChatOpenAI这个构造函数允许我们传递http_client,于是我们就可以对http客户端做一些修改

from langchain_openai import ChatOpenAI  import logging  logging.basicConfig(level=logging.DEBUG)    import httpx  def log_request(request):      print(f"Request: {request.method} {request.url}")      print("Headers:", request.headers)      print("Body:", request.content.decode())    def log_response(response):      response.read()      print(f"Response: {response.status_code}")      print("Headers:", response.headers)      print("Body:", response.text)    client = httpx.Client(      event_hooks={          "request": [log_request],          "response": [log_response],      }  )    llm = ChatOpenAI(      model="llama3:8b",      base_url="http://localhost:11434/v1",      api_key="123456",      http_client=client  )  response = llm.invoke("What are you?")

给httpx.Client设置请求和响应的hook,让它在发送请求和收到响应后打印请求和相应信息。现在再运行代码,会看到更详细的日志

Request: POST http://localhost:11434/v1/chat/completionsHeaders: Headers({'host': 'localhost:11434', 'accept-encoding': 'gzip, deflate, zstd', 'connection': 'keep-alive', 'accept': 'application/json', 'content-type': 'application/json', 'user-agent': 'OpenAI/Python 1.76.0', 'x-stainless-lang': 'python', 'x-stainless-package-version': '1.76.0', 'x-stainless-os': 'MacOS', 'x-stainless-arch': 'arm64', 'x-stainless-runtime': 'CPython', 'x-stainless-runtime-version': '3.10.16', 'authorization': '[secure]', 'x-stainless-async': 'false', 'x-stainless-retry-count': '0', 'content-length': '91'})Body: {"messages":[{"content":"What are you?","role":"user"}],"model":"llama3:8b","stream":false}...Response: 200Headers: Headers({'content-type': 'application/json', 'date': 'Thu, 01 May 2025 06:29:08 GMT', 'content-length': '1262'})Body: {"id":"chatcmpl-96","object":"chat.completion","created":1746080948,"model":"llama3:8b","system_fingerprint":"fp_ollama","choices":[{"index":0,"message":{"role":"assistant","content":"I am LLaMA, an AI assistant developed by Meta AI ... when needed."},"finish_reason":"stop"}],"usage":{"prompt_tokens":14,"completion_tokens":184,"total_tokens":198}}

这下程序和后端大模型API服务的http请求响应信息都完整的打印出来了。这里引申出一个问题

必须使用ChatOpenAI才能得到http请求和响应信息吗?

当前的 ChatOpenAI(版本0.3.14)支持我们传入http_client参数,所以我们才有机会通过hook来打印http信息。我查看了下面几个chat model,发现它们都不支持http_client的传入,所以这个方案必须要使用ChatOpenAI。

但这同时也带来一个使用的限制:后端大模型服务必须要兼容OpenAI的API规范(否则无法使用ChatOpenAI和他们通信)。

好了,文章到此结束,希望能给你带来一些帮助。

本文由博客一文多发平台 OpenWrite 发布!

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

LangChain LLM调试 ChatOpenAI HTTP日志
相关文章