☰
Hindsight:面向LLM API的轻量级可观测性与调试工具
2026/10/1 1:42:05 网站建设 项目流程

1. 项目概述:Hindsight 不是“事后诸葛亮”,而是一套可落地的 LLM API 调试与可观测性工程实践

“Hindsight”这个词在日常语境里常被译作“后见之明”——事情发生之后才看清楚前因后果。但放在当前 LLM 工程落地的现实场景中,它早已脱离了哲学隐喻,演变成一个极具实操价值的技术代号:一套面向生产级大模型 API 调用链路的轻量级可观测性(Observability)与调试辅助系统。它不训练模型、不优化推理、不封装框架,而是专注解决一个每天都在高频发生的痛点:当你的 Python 脚本调用 OpenAI / DeepSeek / 智谱 API 突然报错时,你能不能在 30 秒内精准定位是 key 写错了、organization 被禁用、context 超长、还是 Docker 容器里根本没把环境变量传进去?Hindsight 的核心价值,就藏在这个“30 秒”里。

我从 2022 年底开始密集接入各类 LLM API,经手过 17 个不同厂商的 SDK,部署过 42 个基于 Flask/FastAPI 的推理服务,踩过的坑几乎覆盖了热搜词列表里的每一条:unexpected status 401 unauthorized: incorrect api key provided: sk-svcac****这类错误我见过不下 200 次;api error: 400 this model's maximum context length is 1048576 tokens这种提示在处理长文档摘要时每周必现;docker desktop 启动失败导致本地调试环境瘫痪更是家常便饭。Hindsight 就是在这些血泪经验里长出来的——它不是另一个 LLM 框架,而是一个“API 调用黑匣子记录仪”。它会在每次请求发出前自动捕获完整的上下文:你传了什么 prompt、用了哪个 model、设置了哪些 temperature/top_p 参数、环境变量里实际读到的 API Key 是什么(注意:是明文记录,但仅存于本地日志,不上传、不加密、不联网)、Docker 容器的 hostname 和 network mode 是什么、甚至 Python 进程启动时的sys.argv都会快照一份。当错误发生时,你不需要翻 5 个终端窗口去拼凑线索,直接打开 Hindsight 生成的结构化日志文件,就能看到一条时间线清晰、字段完备的“事故还原报告”。

这个项目特别适合三类人:第一类是正在用 LangChain/LlamaIndex 快速搭建 PoC 的算法同学,你们需要快速验证想法,而不是花半天时间 debug 环境配置;第二类是负责将 LLM 功能集成进现有业务系统的后端工程师,你们面对的是多租户、多模型、多 Key 的复杂调度场景,Hindsight 提供的 request_id 全链路追踪能直接对接你们已有的 ELK 或 Grafana;第三类是技术决策者或 MLOps 工程师,你们关心的是如何建立 LLM 服务的 SLO(Service Level Objective),比如“99% 的 /v1/chat/completions 请求应在 2s 内返回非 4xx/5xx 响应”,Hindsight 输出的 CSV 日志可直接喂给 Prometheus 的 pushgateway,生成实时可用的 SLI 监控看板。它不替代 OpenTelemetry,但比 OpenTelemetry 在 LLM 场景下轻量 10 倍;它不取代 Sentry,但比 Sentry 对401 Unauthorized这类业务层错误的诊断粒度更细。如果你的团队还在靠print("key:", os.getenv('OPENAI_API_KEY'))来排查问题,那 Hindsight 就是你今天最该装上的那个 pip 包。

2. 核心设计思路拆解:为什么不用现成的 APM 工具,而要自己造这个“黑匣子”

2.1 LLM API 调用链路的特殊性决定了通用 APM 的失效

市面上主流的 APM(Application Performance Monitoring)工具,如 Datadog、New Relic、SkyWalking,其设计哲学是围绕传统 Web 服务构建的:HTTP 请求 → 应用逻辑 → 数据库查询 → 返回响应。它们擅长追踪 SQL 执行耗时、Redis 缓存命中率、JVM GC 时间等指标。但 LLM API 调用链路存在三个根本性差异,导致这些工具要么“看不见”,要么“看不准”。

第一,关键瓶颈不在本地代码,而在网络与远端服务。一个典型的openai.ChatCompletion.create()调用,90% 的时间消耗在 DNS 解析、TLS 握手、数据上传、远端模型推理、流式响应接收这五个网络阶段。而传统 APM 的span(跨度)通常只覆盖requests.post()方法的执行时间,它无法告诉你这 1.8 秒里,有 0.3 秒卡在 DNS,0.5 秒耗在 TLS,0.7 秒是模型在思考——这些信息恰恰是优化的关键。Hindsight 的设计起点就是“把网络层的毛细血管也纳入观测”。它通过 monkey patchurllib3的HTTPConnectionPool.urlopen方法,在真正发起 HTTP 请求前,精确记录socket.gethostbyname()的返回值和耗时、ssl.SSLContext.wrap_socket()的握手时间戳、以及send()和recv()的字节级吞吐量。这些数据以微秒级精度写入日志,形成一张真实的“网络健康地图”。

第二,错误语义高度业务化,4xx/5xx 状态码只是表象。401 Unauthorized在 RESTful API 中通常意味着认证失败,但在 LLM 场景下,它可能对应至少五种完全不同的根因:API Key 字符串末尾多了个空格、Organization ID 被管理员禁用、Key 绑定的 Billing Plan 已超限、Key 所属的 Project 处于暂停状态、甚至是你调用的 endpoint URL 写成了https://api.openai.com/v1/chat/completions(正确)而非https://api.openai.com/v1/chat/completion(少了个 s)。通用 APM 只会标记这是一个 401 错误,而 Hindsight 会在日志中额外记录response.headers.get('x-ratelimit-remaining')、response.headers.get('x-request-id')、以及最关键的一行:response.json().get('error', {}).get('message', '')。正是这行 message,把模糊的“未授权”翻译成了可操作的“Your organization has been disabled. An organization admin can re-enable it.”。我曾用这一行 message 直接触发企业微信机器人告警,让运维同事在 2 分钟内完成组织恢复,而不是等业务方打电话来投诉。

第三,上下文爆炸式增长,传统日志格式无法承载。LLM 的输入不再是几个 query string 参数,而是一个嵌套三层的 JSON:messages数组里每个元素都有role和content,content本身可能是上千字的 Markdown 文档;tools参数里又定义了一组 JSON Schema;response_format还可能要求强制输出特定结构。一个完整的请求体轻松突破 10KB。通用日志系统(如 Filebeat + Logstash)在处理这种大 payload 时,要么因默认的max_line_length截断,要么因 JSON 解析失败而丢弃整条日志。Hindsight 的解决方案很“土”但极其有效:它不尝试解析整个 JSON,而是用正则预扫描,提取出messages[0].content的前 200 字符(带省略号)、messages[-1].content的长度、tools数组的长度、以及model字段的精确值。这些“摘要特征”被扁平化为 CSV 的列,确保日志既可读又可查;而完整的原始 payload,则单独保存为一个以request_id命名的.json文件,按日期归档到./hindsight/logs/payloads/2024-06-15/目录下。这种“摘要+全量”的双轨制,是平衡可观测性与存储成本的核心设计。

2.2 Docker 环境下的可观测性必须穿透容器边界

热搜词里反复出现docker desktop、windows 安装 docker、docker 安装 mysql8.0,这说明大量 LLM 应用正运行在容器化环境中。而 Docker 带来的最大可观测性挑战,是环境变量的不可见性。你在宿主机上export OPENAI_API_KEY=sk-xxx,然后docker run -e OPENAI_API_KEY my-llm-app,你以为 Key 一定传进去了?不一定。因为docker run命令里的-e参数,只会在容器启动时将环境变量注入到/proc/1/environ,而 Python 进程如果是在容器内通过supervisord或entrypoint.sh启动的,它读取的os.environ可能来自另一个进程树。更隐蔽的是.env文件:很多 FastAPI 项目依赖python-dotenv加载.env,但如果你的 Dockerfile 是COPY . /app,而.env文件被.dockerignore忽略了,那么容器里根本不存在这个文件,dotenv会静默失败,os.getenv('OPENAI_API_KEY')返回None,最终导致401错误——而你查遍所有日志,都看不到任何关于.env加载失败的提示。

Hindsight 的应对策略是“主动取证,而非被动监听”。它在每次发起 API 请求前,不依赖os.getenv(),而是直接读取 Linux 系统的/proc/<pid>/environ文件(其中<pid>是当前 Python 进程的 PID)。这个文件是二进制格式,用\x00分隔每个KEY=VALUE对,Hindsight 用ctypes调用libc的open()和read()系统调用,将其完整读出并解析。结果会记录在日志的env_snapshot字段里,例如:

env_snapshot: {"OPENAI_API_KEY": "sk-svcac***REDACTED***", "OPENAI_ORG_ID": "org-xxx", "HOSTNAME": "f8a2b1c4d5e6", "PATH": "/usr/local/bin:/usr/bin:/bin"}

注意,这里对 API Key 做了REDACTED处理,但保留了前缀sk-svcac—— 这个前缀足以帮你确认 Key 的类型(OpenAI 的 service account key)和是否被截断,同时满足安全审计要求。更重要的是,HOSTNAME字段明确告诉你这个请求来自哪个容器,结合docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}",你能瞬间定位到是llm-gateway-1还是>import hindsight hindsight.enable() # 无参数,开箱即用

然后,你所有的openai.ChatCompletion.create()、openai.Images.generate()、openai.Beta.Threads.create()调用,都会被自动观测。它不依赖asyncio,所以同步和异步 SDK 都支持;它不修改sys.path,所以与virtualenv、poetry、conda完全兼容;它甚至不创建任何后台线程,所有日志写入都是同步的(可通过hindsight.configure(async_mode=True)开启异步,但默认关闭以保证最小干扰)。这种“润物细无声”的设计,是我过去三年里,唯一一个被团队所有成员自发采用、且从未被抱怨“太重”的可观测性工具。

3. 核心细节解析与实操要点:从安装到定制化的完整路径

3.1 安装与初始化:三步走,5 分钟完成接入

Hindsight 的安装设计得像pip install requests一样简单,但背后隐藏着针对不同部署场景的精细考量。整个过程分为三个明确步骤,每一步都有其不可替代的作用。

第一步:基础安装与依赖检查

在你的项目虚拟环境中,执行:

pip install hindsight

这条命令会安装hindsight包及其两个硬依赖:pydantic>=2.0.0(用于日志结构的强类型校验)和rich>=13.0.0(用于终端日志的彩色高亮输出)。它故意不安装openai、httpx或aiohttp。这是经过深思熟虑的:Hindsight 的目标是成为所有 LLM SDK 的“通用观测层”,而不是绑定在某一个 SDK 上。如果你的项目已经安装了openai==1.35.0,Hindsight 会自动适配;如果你用的是httpx直接调用 DeepSeek API,Hindsight 提供了hindsight.patch_httpx()的手动 patch 接口;如果你用的是curl命令行,Hindsight 还有一个独立的hindsight-cli子命令,可以对任意curl调用进行包裹观测。这种“依赖解耦”设计,让你可以在不改动现有技术栈的前提下,渐进式地引入可观测性。

第二步:全局启用与基础配置

在你的主程序入口文件(如main.py或app.py)的最顶部,添加:

import hindsight # 启用 Hindsight,默认配置 hindsight.enable() # (可选)自定义日志目录和级别 hindsight.configure( log_dir="./hindsight_logs", log_level="INFO", # DEBUG/INFO/WARNING/ERROR max_payload_size_kb=512, # 超过此大小的 payload 将被截断 redact_api_keys=True, # 是否对 API Key 进行脱敏 )

hindsight.configure()的每一个参数都直指生产痛点。log_dir默认是./hindsight_logs,但你可以指定为/var/log/my-llm-app/hindsight,以便与系统日志统一管理;max_payload_size_kb是防止日志磁盘爆满的关键开关——我曾见过一个客户因为忘记设置此项,单日生成了 47GB 的payloads/JSON 文件,最终导致服务器磁盘 100%;redact_api_keys=True是安全底线,它使用确定性哈希(SHA256)对 Key 的主体部分进行替换,确保即使日志被意外泄露,也无法反推出原始 Key。

第三步:Docker 环境专项配置

当你将应用打包进 Docker 镜像时,必须显式地将 Hindsight 的日志目录挂载为卷(volume),否则容器退出后日志将全部丢失。一个典型的docker-compose.yml片段如下:

version: '3.8' services: llm-api: build: . environment: - OPENAI_API_KEY=${OPENAI_API_KEY} - OPENAI_ORG_ID=${OPENAI_ORG_ID} volumes: - ./hindsight-logs:/app/hindsight_logs # 关键!将宿主机目录挂载进容器 - /etc/timezone:/etc/timezone:ro # 确保容器内时间与宿主机一致 logging: driver: "json-file" options: max-size: "10m" max-file: "3"

这里有两个极易被忽略的细节。第一,volumes挂载必须使用绝对路径(./hindsight-logs是相对路径,Docker Compose 会自动解析为绝对路径),且挂载点'/app/hindsight_logs'必须与hindsight.configure(log_dir=...)中指定的路径完全一致。第二,/etc/timezone的挂载是为了规避 Docker 容器时区不一致导致的日志时间戳错乱。我曾在一个跨时区团队中,因为容器时区是 UTC 而宿主机是 CST,导致所有401错误日志的时间戳都显示为“凌晨 3 点”,让值班同学误以为是定时任务出了问题,白白排查了 2 小时。这个小技巧,值得你把它写进团队的 Docker 最佳实践文档里。

3.2 日志结构详解:读懂每一条记录背后的“故事”

Hindsight 生成的日志不是杂乱的文本流,而是一个精心设计的、可编程解析的结构化数据集。理解其字段含义,是高效利用它的前提。日志以 CSV 格式为主(便于 Excel 和 Pandas 分析),辅以 JSON 全量 payload。我们以一次典型的chat.completions调用失败为例,解析其 CSV 记录的关键字段:

字段名示例值含义与实战价值
timestamp2024-06-15T14:23:45.123456+08:00ISO 8601 格式带时区的时间戳。注意:它来自datetime.now().astimezone(),而非time.time(),确保跨时区团队看到的是同一时刻。
request_idreq_abc123def456全局唯一请求 ID,由uuid.uuid4()生成。这是你串联所有日志的“黄金线索”。在 Kibana 里搜索request_id: "req_abc123def456",就能找到这次请求的全部上下文。
sdkopenai-python调用的 SDK 名称和版本,如openai-python-1.35.0。当你升级 SDK 后遇到新 bug,可以用这个字段快速筛选出所有旧版本日志进行对比。
methodPOSTHTTP 方法,永远是POST,因为所有 LLM API 都是 POST。
endpointhttps://api.openai.com/v1/chat/completions实际请求的 URL。这是排查404 Not Found的第一现场。如果这里显示的是https://api.openai.com/v1/chat/completion(少了个 s),那错误原因立刻明了。
modelgpt-4-turbo请求的模型名称。结合status_code,你可以快速发现“为什么调用gpt-3.5-turbo是 200,而gpt-4-turbo却是 400?”——答案往往是gpt-4-turbo的 context limit 更高,而你的 prompt 超限了。
prompt_tokens1248估算的输入 token 数量(使用 tiktoken 库)。这是400 context length exceeded错误的直接证据。如果prompt_tokens是1048576,而错误提示说maximum context length is 1048576 tokens,那说明你的 prompt 已经顶格,再加一个字符就会失败。
status_code401HTTP 状态码。Hindsight 会为所有 4xx/5xx 状态码自动添加error_type字段(见下)。
error_typeAUTH_UNAUTHORIZEDHindsight 定义的标准化错误类型。它将原始的401映射为AUTH_UNAUTHORIZED,429映射为RATE_LIMIT_EXCEEDED,503映射为SERVICE_UNAVAILABLE。这个字段是做自动化告警的基础,比status_code更具业务语义。
error_messageIncorrect API key provided: sk-svcac***从response.json().get('error',{}).get('message')中提取的原始错误信息。这是所有字段中信息密度最高的一个。它直接告诉你 root cause,无需二次解析。
env_hostnamellm-api-789容器的 hostname。结合docker ps,可精确定位故障实例。
env_openai_key_prefixsk-svcacAPI Key 的前缀。用于快速识别 Key 类型(sk-是 OpenAI,ak-是智谱,sk-xxx是 DeepSeek),并确认 Key 是否被截断。
network_dns_time_ms12.45DNS 解析耗时(毫秒)。如果这个值 > 100ms,说明你的 DNS 服务器可能有问题,需要检查/etc/resolv.conf。
network_tls_time_ms89.21TLS 握手耗时(毫秒)。如果这个值异常高(> 500ms),通常是证书链不完整或中间 CA 服务器响应慢,需要检查openssl s_client -connect api.openai.com:443。
duration_ms1842.67整个请求的总耗时(毫秒)。这是计算 P95/P99 延迟的原始数据。

这张表格,本质上是一份“LLM API 故障诊断速查表”。当你收到一个401报警时,你应该按以下顺序查看字段:error_message→env_openai_key_prefix→env_hostname→endpoint。这个顺序,就是我过去一年里总结出的、最快定位 90%401问题的黄金路径。它把一个需要经验判断的模糊问题,变成了一个机械式的、可复制的排查流程。

3.3 高级定制:从日志过滤到自定义 Hook 的深度控制

Hindsight 的默认配置能满足 80% 的场景,但当你进入更复杂的生产环境时,就需要用到它的高级定制能力。这些能力不是炫技,而是为了解决真实世界中的棘手问题。

日志过滤:只记录你关心的流量

在一个大型 LLM 网关服务中,你可能同时代理了 OpenAI、Anthropic、Google Gemini 的请求。但你只想对 OpenAI 的chat.completions流量进行深度观测,而对其他请求只记录基本指标(status_code,duration_ms)。Hindsight 提供了hindsight.filter()函数来实现这一点:

import hindsight def openai_chat_filter(request): """只对 OpenAI chat.completions 请求启用全量观测""" if (request.sdk == "openai-python" and request.endpoint.endswith("/chat/completions") and request.method == "POST"): return True # 启用全量观测 else: return False # 只记录基础字段 hindsight.filter(openai_chat_filter) hindsight.enable()

这个 filter 函数会在每次请求前被调用,返回True表示启用 Hindsight 的全部功能(环境快照、网络测量、payload 摘要),返回False则只记录timestamp,request_id,sdk,endpoint,status_code,duration_ms这六个最轻量的字段。我用这个功能,在一个日均 200 万次请求的网关上,将 Hindsight 的日志体积从每天 12GB 降低到了 1.8GB,而关键的 OpenAI 故障分析能力丝毫未损。

自定义 Hook:注入业务上下文

Hindsight 的核心日志字段是固定的,但你的业务可能有独特的上下文需要关联。比如,你的 LLM 服务是为一个在线教育平台提供作文批改,那么每次请求都应该带上student_id和assignment_id。Hindsight 允许你通过hindsight.add_context()注入任意键值对:

from fastapi import Request, Depends import hindsight async def get_student_context(request: Request): # 从 JWT Token 或 Header 中提取学生信息 student_id = request.headers.get("X-Student-ID") assignment_id = request.query_params.get("assignment_id") # 将业务上下文注入 Hindsight hindsight.add_context({ "student_id": student_id, "assignment_id": assignment_id, "course_name": "HighSchool_English" }) @app.post("/api/grade-essay") async def grade_essay(essay: str, request: Request): await get_student_context(request) # 在业务逻辑前注入 # ... 调用 openai.ChatCompletion.create()

注入的上下文会自动合并到每一条日志记录中,出现在 CSV 的额外列里,如student_id,assignment_id,course_name。这意味着,当你在日志中发现一个400 context length exceeded错误时,你可以直接知道这是student_id=STU-789012在提交assignment_id=ASSIGN-456时发生的,并且这个学生正在上HighSchool_English课。这种将可观测性与业务域模型打通的能力,是 Hindsight 区别于所有通用 APM 工具的核心竞争力。

错误自动恢复:从观测到行动的闭环

最强大的可观测性,不是告诉你哪里错了,而是帮你自动修复。Hindsight 提供了一个实验性的on_error回调机制,允许你在捕获到特定错误时,执行自定义的恢复逻辑:

import hindsight import os def handle_401_error(request, response): """当检测到 401 时,尝试从备用 Key 池中切换""" if response.status_code == 401: # 从 Redis 或数据库中获取下一个备用 Key new_key = get_next_backup_key() if new_key: # 动态更新环境变量(仅对当前进程有效) os.environ["OPENAI_API_KEY"] = new_key # 记录切换事件 hindsight.log_event("KEY_ROTATED", {"old_key_prefix": request.env_openai_key_prefix, "new_key_prefix": new_key[:8]}) return True # 表示已处理,Hindsight 将不再抛出原始异常 return False # 表示未处理,让原始异常继续向上抛出 hindsight.on_error(handle_401_error) hindsight.enable()

这个handle_401_error回调函数,在每次401响应被 Hindsight 捕获后立即执行。如果它返回True,Hindsight 会静默吞掉这个错误,并让上层代码认为这次请求“成功”了(当然,实际的response对象已经被替换了)。这为构建高可用的 LLM 服务提供了底层支撑。当然,这个功能需要谨慎使用,因为它改变了程序的控制流。我的建议是:只在on_error回调里做“无副作用”的操作(如发告警、记日志、切 Key),而不要做“有状态变更”的操作(如修改数据库、发邮件),后者应该交给专门的告警服务去处理。

4. 实操过程与核心环节实现:从零开始搭建一个可运行的 Hindsight 环境

4.1 本地开发环境搭建:Windows/Mac/Linux 三端实测指南

Hindsight 的设计目标是“一次编写,随处运行”,但不同操作系统的底层差异,确实会带来一些需要手动干预的细节。下面是我亲自在 Windows 11(WSL2)、macOS Sonoma、Ubuntu 22.04 上完整测试过的、确保 100% 成功的搭建流程。每一步都标注了“为什么这么做”,避免你成为“复制粘贴工程师”。

第一步:Python 环境准备(所有平台通用)

Hindsight 要求 Python >= 3.8,推荐使用 3.10 或 3.11。强烈建议不要使用系统自带的 Python(尤其是 macOS),因为它的包管理器(/usr/bin/python3)经常与系统更新冲突。请统一使用pyenv进行版本管理:

# macOS (使用 Homebrew) brew install pyenv pyenv install 3.11.9 pyenv global 3.11.9 # Ubuntu/WSL2 (使用 apt) sudo apt update && sudo apt install -y make build-essential libssl-dev zlib1g-dev \ libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev \ libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python-openssl git curl https://pyenv.run | bash # 将 pyenv 初始化脚本添加到 ~/.bashrc 或 ~/.zshrc export PYENV_ROOT="$HOME/.pyenv" command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)" pyenv install 3.11.9 pyenv global 3.11.9

提示:pyenv是 Python 版本管理的行业标准。它能让你在同一个机器上无缝切换多个 Python 版本,避免pip包冲突。我见过太多团队因为混用系统 Python 和 Anaconda Python,导致hindsight安装后import失败,根源就是pip和python不是同一个环境。

第二步:创建项目骨架与安装 Hindsight

新建一个项目目录,初始化虚拟环境:

mkdir hindsight-demo && cd hindsight-demo python -m venv venv source venv/bin/activate # Linux/macOS # venv\Scripts\activate.bat # Windows CMD # venv\Scripts\Activate.ps1 # Windows PowerShell (需先 Set-ExecutionPolicy RemoteSigned) pip install --upgrade pip pip install hindsight openai

注意:在 Windows PowerShell 中,直接运行Activate.ps1会因执行策略被阻止。这是 Windows 的安全机制,不是 Hindsight 的问题。执行Set-ExecutionPolicy RemoteSigned -Scope CurrentUser即可永久解决。这个命令只影响当前用户,不会降低系统安全性。

第三步:编写一个会出错的测试脚本

创建test_hindsight.py,故意制造一个401错误,以验证 Hindsight 是否正常工作:

import os import time import hindsight import openai # 启用 Hindsight,配置日志目录 hindsight.configure(log_dir="./hindsight_logs", log_level="DEBUG") hindsight.enable() # 设置一个错误的 API Key(故意少一位) os.environ["OPENAI_API_KEY"] = "sk-svcac12345678901234567890123456789012345678901234567890123456789" # 模拟一次请求 try: response = openai.chat.completions.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Hello, world!"}] ) print("Success:", response.choices[0].message.content) except Exception as e: print("Error:", e) # 等待日志写入完成 time.sleep(1)

第四步:运行并验证日志输出

执行脚本:

python test_hindsight.py

如果一切顺利,你应该看到终端输出类似这样的彩色日志(rich库的效果):

[bold red]❌ Hindsight Capture[/bold red] | [green]401[/green] | [yellow]openai-python-1.35.0[/yellow] | [cyan]gpt-3.5-turbo[/cyan] [blue]Endpoint:[/blue] https://api.openai.com/v1/chat/completions [blue]Error:[/blue] Incorrect API key provided: sk-svcac12345678901234567890123456789012345678901234567890123456789 [blue]Duration:[/blue] 1245.67 ms | [blue]DNS:[/blue] 12.45 ms | [blue]TLS:[/blue] 89.21 ms

同时,检查./hindsight_logs/目录,你应该能看到:

  • hindsight-2024-06-15.csv:CSV 格式的结构化日志。
  • payloads/2024-06-15/req_abc123def456.json:完整的请求和响应 payload。

打开 CSV 文件,用 Excel 或 VS Code 的 CSV Preview 插件查看,确认error_message字段是否包含了你期望的错误文本。这一步的成功,标志着你的本地 Hindsight 环境已经 100% 就绪。

4.2 Docker 环境部署:从 Docker Desktop 到生产集群的平滑过渡

将 Hindsight 从本地迁移到 Docker,是检验其设计是否健壮的关键一环。下面是一个经过生产环境验证的、从Docker Desktop(开发)到Docker Swarm(预发)再到Kubernetes(生产)的平滑过渡方案。

Docker Desktop 本地开发(Windows/macOS)

这是最简单的场景。你只需要一个Dockerfile和一个docker-compose.yml。Dockerfile内容如下:

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询