
这次我们聊的主题不是某个具体模型而是一个正在把 AI 编程工具用户变成真正 AI 工程师的方法论Observability可观测性如何把 Vibe Coding 变成 AI Engineering。Vibe Coding 是依赖 AI 生成代码的开发方式常见于 Cursor、Trae、Copilot 这类工具。你给出意图AI 写代码你凭感觉看结果是否合理。这种节奏很快但问题也很明显项目变大之后回归靠猜、定位靠翻日志、上线不放心。可观测性要解决的正是这件事让 AI 应用和 AI 生成代码的运行过程可回放、可度量、可评测。这篇文章会先讲清楚可观测性为什么是 Vibe Coding 工程化的关键再给一套最小可落地框架包含日志、指标、链路追踪Trace、效果评测四个维度。之后会演示如何用日志记录一次 LLM 调用、如何给批量任务打 Trace、如何观察资源占用最后给一张常见问题排查表。适合正在使用 Cursor、Trae、Copilot 生成代码或者正在开发 RAG、Agent、LLM API 网关的开发者。1. 可观测性核心能力速览先说结论可观测性不是锦上添花的监控而是把 Vibe Coding 从“生成代码”推进到“维护系统”的工程基础设施。能力项说明主题类型AI 应用可观测性与工程化方法论落地形态日志系统、指标采集、链路追踪、效果评测、反馈回收核心能力记录一次 LLM 调用的输入、输出、模型、上下文、Token 数、耗时支持回归评估和批量监控硬件门槛可观测平台本身可在 CPU 机器上运行GPU 只看你是否同时跑本地 LLM 推理显存占用可观测组件通常不依赖 GPU本地推理的显存占用以推理服务实际值为准支持平台Linux、macOS、WindowsWindows 建议使用 WSL2启动方式Docker Compose、云服务、SDK 埋点是否支持 API支持通常通过 SDK 或 HTTP 上报 Trace 和指标是否支持批量任务支持批量任务可按 Trace ID 或任务 ID 聚合适合场景AI 编程、RAG 应用、Agent 系统、LLM API 网关、批量推理任务这里有一个关键点要分清可观测层并不依赖 GPU。很多人以为做 AI 工程就必须先买一张大显存显卡实际上日志、Trace、指标采集这些组件都是轻量服务CPU 机器就能跑。只有当你用本地模型做推理时显存才变成瓶颈。所以这个主题的硬件门槛取决于两部分可观测平台本身1 到 2 台 CPU 机器8G 以上内存磁盘要预留足够日志和 Trace 的存储空间。本地推理服务如果有才需要考虑 GPU 显存。2. 适用场景与使用边界可观测性不是所有团队都需要马上全面铺开但它有非常明确的使用边界。适合的场景包括团队在用 AI 编程工具生成代码但代码合入后经常出现“不知道哪里出了问题”。自建了 RAG 问答系统用户反馈答案不稳定想定位是检索失败、上下文截断还是模型生成问题。开发了 Agent 应用一次任务会多次调用 LLM中间还穿插工具调用需要完整的调用链路。做批量推理任务比如批量摘要、批量翻译、批量图片描述想统计成本、延迟和失败率。正在微调或自定义提示词需要对比不同版本的效果。不适合的场景也很清晰只有一个临时脚本跑完就删不需要长期维护。没有任何用户和业务指标接入只是为了“看起来工程化”而堆监控。团队连基础日志都没有统一格式直接上复杂 Trace 平台会适得其反。使用边界方面合规和安全必须重点说原始 Prompt 和模型输出往往包含用户数据写入日志和 Trace 时必须脱敏。不要在生产日志里记录 API Key、Token、会话 Cookie、身份证号、手机号等敏感信息。如果接入第三方 LLM API要注意数据出境和隐私合规要求最好在自建服务内部做脱敏和审计。涉及人脸、声音、版权素材的生成任务必须确认授权范围。可观测性最大的副作用是“记录得太全”。记录全意味着可以定位问题也意味着一旦存储被攻破风险更大。所以能采样就采样能脱敏就脱敏不要天真地把所有原始数据都堆进一个看板。3. 环境准备与前置条件在开始搭建之前先明确一个原则不要一上来就搭一套完整分布式追踪系统。多数团队连“记录一次 LLM 调用的结构化日志”都没做好直接上复杂平台很容易被成本和无尽维护拖垮。建议的最小前置条件如下操作系统Linux、macOS、Windows 均可Windows 建议用 WSL2。语言环境Python 3.9 或 Node.js 18取决于你用什么 SDK 接入。容器环境如果使用 Docker Compose 部署可观测平台需要提前安装 Docker。数据存储日志和 Trace 会持续增长提前规划磁盘空间建议至少预留 20G 以上。LLM SDK例如 OpenAI、Anthropic、LiteLLM、LangChain、LlamaIndex 等具体取决于你的应用。命令检查示例# 检查 Docker 是否可用 docker --version # 检查 Python 版本 python --version # 检查磁盘空间 df -h如果本地已有模型推理服务比如 vLLM、Ollama、LLaMA.cpp还需要观察 GPU 状态nvidia-smi --query-gpuname,memory.total,memory.used,utilization.gpu --formatcsv可观测平台的部署不需要 GPU但需要足够的 CPU 和内存来处理日志解析、指标抓取和 Trace 存储。如果数据量大建议单独分配一台 4 核 8G 以上的机器。另外一个容易忽略的问题是端口占用。常用端口包括 4317、4318OTLP、9090Prometheus、3000Grafana、8000 或 8080业务服务。启动前先检查# 检查端口是否被占用 lsof -i :4317 lsof -i :9090如果端口被占用换端口即可不要硬启动。4. 最小可观测平台怎么部署这里给出一套通用部署方案OpenTelemetry Collector 负责接收 Trace 和指标Prometheus 负责存储指标Grafana 负责展示。这个组合是目前最通用的自建可观测基础栈。不要把它当成唯一标准而是当成一个起点。你也可以换成托管服务或者直接用 Langfuse、LangSmith、Phoenix 这类 LLM 可观测平台但部署思路是一致的。先创建一个docker-compose.ymlservices: otel-collector: image: otel/opentelemetry-collector-contrib:latest container_name: otel-collector ports: - 4317:4317 - 4318:4318 volumes: - ./otel-config.yml:/etc/otelcol-contrib/config.yaml restart: unless-stopped prometheus: image: prom/prometheus:latest container_name: prometheus ports: - 9090:9090 restart: unless-stopped grafana: image: grafana/grafana:latest container_name: grafana ports: - 3000:3000 environment: - GF_SECURITY_ADMIN_PASSWORDadmin restart: unless-stopped注意实际使用时不要用latest标签应该固定到你验证过的具体版本。这里只是为了演示结构。OpenTelemetry Collector 需要一个最小配置otel-config.ymlreceivers: otlp: protocols: grpc: http: processors: batch: exporters: debug: verbosity: detailed service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [debug] metrics: receivers: [otlp] processors: [batch] exporters: [debug]这个配置的作用是把应用上报的 Trace 和指标打印到 Collector 日志中。先跑通链路再接入真正的存储和看板。启动命令docker compose up -d启动后观察docker logs -f otel-collector如果你看到类似收到 Trace 的日志说明上报链路已经通了。这个阶段最容易出问题的地方有三个镜像拉取慢建议配置容器镜像加速。端口冲突尤其是 4317 和 4318。Collector 配置格式错误YAML 缩进写错会导致启动失败。5. 四个核心维度日志、指标、追踪、评测可观测性在 AI 工程里的落地可以拆成四个维度每一个都有明确作用。5.1 日志日志是最容易启动的维度。统一格式是最关键的一步千万不要再用纯文本随意打印user ask something, success这种日志没法解析也没法检索。建议使用 JSON 结构化日志至少包含时间、Trace ID、模型名、Prompt、输出、状态、耗时。这里有一个最小结构示例{ ts: 2025-05-01T12:00:00.000Z, trace_id: req_123456, model: gpt-4o-mini, prompt: 请把下面这段话翻译成中文, output: 请把下面这段话翻译成中文, status: ok, latency_ms: 320, prompt_tokens: 12, completion_tokens: 15 }注意这个示例只是演示字段不一定需要直接暴露原始 Prompt。生产环境建议只记录 Prompt 的哈希值或者脱敏后的摘要。5.2 指标指标用来回答“整体健康度怎么样”。常见指标包括请求总数按模型、按用户、按接口维度拆分。平均耗时和 P95 耗时。错误率。Token 消耗总量和预估成本。缓存命中率。批量任务成功率。这些指标可以上报到 Prometheus也可以直接输出成结构化日志后聚合。初期不需要做太细先算清三个数请求量、错误率、Token 成本。5.3 链路追踪链路追踪是可观测性的核心。一次用户请求可能经过多个环节用户输入 - 检索召回 - 拼装 Prompt - 调用模型 - 工具调用 - 生成输出如果你只记录应用日志很难把一个请求的完整过程串起来。Trace 就是解决这个问题的每次请求生成一个 Trace ID每个环节是一个 SpanSpan 之间通过 Parent ID 关联。这样排查问题时可以直接还原一次完整调用。最小实现思路import uuid import time import json def start_trace(): trace_id uuid.uuid4().hex root_span_id uuid.uuid4().hex[:8] return { trace_id: trace_id, root_span_id: root_span_id, start_time: time.time() }实际接入时建议使用 OpenTelemetry SDK而不是自己造一套 Span 管理逻辑。自己维护 Trace 结构很容易出错长期成本高。5.4 效果评测日志、指标、追踪解决的是“系统有没有问题”评测解决的是“AI 回答得好不好”。后者是 AI 工程区别于传统后端工程的关键。评测可以从两个层面做离线评测准备一组测试集跑不同模型版本或提示词版本比较输出质量。在线评测在真实用户请求上采集点赞、点踩、复制、重试等信号。在线评测的信号可以当成反馈数据回填到 Trace 中形成闭环{ trace_id: req_123456, feedback: { thumbs_up: false, user_comment: 回答没有命中问题 } }有了反馈下一步才能优化提示词、调整模型、改检索策略。没有反馈所有优化都是自说自话。6. 功能测试与效果验证可观测性不是部署完就结束了你需要验证它真的能帮你发现问题。下面是一组通用验证用例可以直接拿来测。测试项输入示例观测点判断标准基础生成一个简单问答 Prompt是否生成 Trace日志是否记录模型名和耗时有 Trace 和日志回归测试同一组测试集跑两个模型输出内容差异、Token 数差异能对比出质量变化批量任务10 条文本摘要任务每条任务是否有 Trace ID成功率和耗时所有任务都有记录长上下文输入超过模型上下文一半长度的文本是否截断是否超时Token 数是否符合预期能定位到截断位置Agent 工具调用让 Agent 查询天气并执行计算工具调用是否生成独立 Span能看到工具调用的入参和出参成本追踪连续调用 100 次按模型聚合 Token 成本能算出每次请求平均成本测试时注意一个原则不要只看“成功”或“失败”两个状态。AI 应用的失败有很多种请求成功但输出是幻觉。请求成功但检索为空模型只能硬编。请求成功但耗时太长用户体验差。请求成功但 Token 消耗异常成本失控。所以可观测性要同时记录状态、耗时、Token 和输出内容。只有这样后续优化才有依据。7. 接口 API 与批量任务接入如果你开发的是一个 API 服务建议在接口层把 Trace ID 带进上下文并且响应里返回 Trace ID。这样用户报问题的时候你可以直接按 Trace ID 查链路。一个通用批量调用示例import json import time import uuid def run_batch_with_observability(items, call_llm): results [] for item in items: trace_id uuid.uuid4().hex start time.perf_counter() try: output call_llm(item[prompt]) status ok except Exception as exc: output str(exc) status error latency_ms round((time.perf_counter() - start) * 1000, 2) record { trace_id: trace_id, task_id: item.get(task_id), prompt: item[prompt], output: output, status: status, latency_ms: latency_ms, ts: time.time() } results.append(record) print(json.dumps(record, ensure_asciiFalse)) return results这个示例的核心思路是批量任务里的每一条数据都带上独立 Trace ID最后汇总成 JSONL 文件。如果你使用的可观测平台有自己的 SDK就用 SDK 上报而不是只打印日志。假设你要把 Trace 上报到自建 Collector 的 HTTP 端点上报逻辑可以写成这样import requests def report_trace(trace_payload, endpointhttp://127.0.0.1:4318/v1/traces): response requests.post(endpoint, jsontrace_payload, timeout5) response.raise_for_status()注意这个代码里的 endpoint 是示例实际接入时要以 OpenTelemetry Collector 实际暴露的地址和协议为准。如果先用自定义 HTTP 上报建议在内部定义一个统一结构避免不同模块上报格式不一致。批量任务最容易被忽略的是“失败重试”。建议在批量脚本里加两个字段attempt当前第几次尝试。error_type错误类型比如超时、限流、上下文过长、模型不可用。这样后续统计失败原因时可以直接按error_type分组而不是只看到一堆 error。8. 资源占用与性能观察可观测性本身会增加少量资源开销但只要控制好采样率影响通常可以忽略。重点观察这几个指标观察对象命令或工具关注点容器资源docker statsCPU、内存、网络流量GPU 显存nvidia-smi显存占用和 GPU 利用率Collector 日志docker logs -f otel-collector是否有 Trace 上报错误日志增长du -sh /var/log/your_app磁盘占用是否过快Trace 存储数据库表大小是否需要采样和清理资源占用和几个因素直接相关上报频率。是否记录完整输入输出。是否保留原始 Prompt。采样率设置。如果觉得开销大可以按下面顺序降低降低采样率比如只采样 10% 的请求。去掉低价值日志的完整输出只保留截断版本。批量上报 Trace而不是每一条独立发一次请求。对静态资源和健康检查请求不打 Trace。本机部署时的实际操作建议# 观察容器资源占用 docker stats # 观察 GPU 显存 nvidia-smi -l 2在批量任务场景下重点观察批量脚本进程的内存。如果一个批次加载了过多长文本进程内存会快速增长卡住时通常不是 CPU 满而是内存不足。9. 常见问题与排查方法下面是一张通用问题排查表适合应用通过可观测性链路定位问题时参考。问题现象可能原因排查方式解决方案日志里没有 Trace ID请求入口没有初始化 Trace检查入口中间件或装饰器在入口统一生成 Trace IDTrace 有 Span 但无法串联Parent Span ID 未传递检查异步任务是否传递上下文异步任务显式传递 Trace 上下文模型调用超时网络慢、模型排队、上下文过长看耗时分布和 Token 数设置超时重试压缩上下文输出质量突然下降Prompt 版本变更或模型版本切换对比不同 Trace 的 model 和 prompt固定模型版本配置回滚机制Token 成本异常上下文重复拼接或 Agent 死循环按 trace_id 查 Token 消耗加缓存限制最大轮数批量任务卡住某条任务触发重试死循环看 attempt 和 error_type设置最大重试次数和熔断日志磁盘写满记录了完整输入输出查看日志文件大小截断输出提升采样率隐私数据泄漏原始 Prompt 直接入库检查日志字段脱敏后再写入API 上报失败Collector 地址错误或端口不通检查容器日志确认端口和地址所有这些排查的前提都是你有日志和 Trace。如果什么都没有遇到问题就只能重新跑一遍或者靠用户复现这是 Vibe Coding 项目最容易失控的地方。10. 最佳实践从 Vibe Coding 走向 AI Engineering 的落地清单最后给一份可操作的落地清单不需要一次全部做完按顺序逐步推进。第一步统一结构日志。所有 LLM 调用都输出 JSON 日志包含 Trace ID、模型、状态、耗时、Token 数。这一步可以直接替换掉项目里随意的 print 日志收益最明显。第二步给关键业务请求打 Trace。从一个入口请求开始记录从用户输入到模型输出的完整链路。异步任务要特别小心上下文传递最好在任务开始时重新创建 Trace。第三步建立在线反馈通道。在生成结果的 UI 上增加有用、无用的反馈按钮反馈数据关联到 Trace。这是后续优化提示词和模型的重要依据。第四步做批量任务的成本和质量统计。批量任务必须记录成功率、平均耗时、Token 消耗和失败原因否则跑一次长任务你都说不清楚它到底做完了没有。第五步设置采样和脱敏策略。默认不记录敏感字段线上日志默认脱敏。所有原始 Prompt 和输出在展示前都过一遍脱敏规则。第六步把可观测性和代码审查、测试流程结合起来。AI 生成的代码合入前除了看功能还要看是否新增了日志、是否传播了 Trace ID、是否引入了未被观测的第三方调用。最后一件事不要迷信“上了一个平台就等于工程化”。可观测性平台的搭建只占三成工作量剩下七成在数据规范、SLA 定义、反馈闭环和日常排障习惯。一个团队只要能在一小时内定位一次坏请求的完整链路就已经比大多数只靠 Vibe Coding 写代码的团队强很多了。如果你正在用 Cursor、Trae、Copilot 这类工具大规模生成代码建议先做一件事跑一个批量任务把每个请求的耗时、状态、Token 数、错误类型都记录下来。看到数据的瞬间你会重新理解什么叫“可观测性把 Vibe Coding 变成 AI Engineering”。建议收藏备用下次用 AI 编程到一半却没有日志能查的时候回来按这份清单补数据链路。