Hindsight 监控指南:Prometheus 指标、健康探针与 OpenTelemetry 分布式追踪
2026/9/15 19:32:59 网站建设 项目流程

Hindsight 监控指南:Prometheus 指标、健康探针与 OpenTelemetry 分布式追踪

【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight

Hindsight(Agent Memory That Learns)通过三条互补的通道提供完整的可观测性:Prometheus 指标(/metrics端点)、三个语义不同的健康端点(/health/live/health/ready/health)以及遵循 GenAI 语义约定(v1.37+)的 OpenTelemetry 分布式追踪。本文以 monitoring.md 为主线,结合仓库中的 metrics.py、tracing.py、liveness.py 以及 monitoring 启动脚本 等实现,系统讲解如何在本地一键拉起 Grafana LGTM 可观测栈、正确配置健康探针(避免把数据库抖动升级成停机事故)、理解每一类指标与标签的语义,并利用现成的 Grafana 仪表盘与示例 PromQL 查询完成生产级告警。

本地可观测栈:一条命令启动 Grafana LGTM

Hindsight 为本地开发提供了开箱即用的 Grafana LGTM(Loki、Grafana、Tempo、Mimir)一体化栈,一条命令即可启动:

./scripts/dev/start-monitoring.sh

该脚本是 start.sh 的便捷包装,后者会先探测 API 是否已在运行(curl http://localhost:8888/metrics),未检测到时给出警告并提示先通过./scripts/dev/start-api.sh启动 API,随后调用docker-compose up拉起整个栈。从 docker-compose.yaml 可以看到,它基于grafana/otel-lgtm:latest镜像启动一个名为hindsight-monitoring的容器,并做了三处关键配置:

  • 端口映射3000(Grafana UI)、4317(OTLP gRPC 追踪)、4318(OTLP HTTP 追踪);
  • 匿名管理员登录GF_AUTH_ANONYMOUS_ENABLED=trueGF_AUTH_ANONYMOUS_ORG_ROLE=AdminGF_AUTH_DISABLE_LOGIN_FORM=true,本地开发无需登录;
  • 挂载 Prometheus 配置与 Hindsight 仪表盘:用 prometheus.yml 覆盖 LGTM 默认抓取配置,并把三个 Hindsight 仪表盘 JSON 挂载进容器,通过 grafana-dashboards.yaml 自动 provisioning。

启动后即可获得:

能力地址 / 说明
Grafana UIhttp://localhost:3000(匿名 admin 访问)
追踪(Tempo)OTLP 端点 http://localhost:4318(HTTP)与 http://localhost:4317(gRPC)
指标(Prometheus/Mimir)自动抓取 http://localhost:8888/metrics
日志(Loki)日志聚合
预置仪表盘Hindsight Operations、LLM Metrics、API Service

值得注意的细节是 prometheus.yml 中的抓取配置:它同时声明了hindsight-apihost.docker.internal:8888)和hindsight-workerhost.docker.internal:8889)两个 job,配合extra_hosts: "host.docker.internal:host-gateway"让容器能访问宿主机上的服务;scrape_interval: 5sevaluation_interval: 5s,并开启了scrape_native_histograms: true以支持原生直方图。注释明确说明 worker 的 job 在宿主机没有运行 worker 时是"无害的空操作"——这为后续生产环境抓取独立 worker 指标提供了现成模板。

在 API 中启用追踪:

export HINDSIGHT_API_OTEL_TRACES_ENABLED=true export HINDSIGHT_API_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318

:::note 生产环境部署 本地监控栈仅用于开发。生产环境应单独部署 Grafana LGTM,或使用商业平台(Grafana Cloud、DataDog、New Relic 等)。 :::

健康端点:区分存活与就绪,避免把数据库抖动变成停机

API 服务端(端口 8888)与每个 worker(端口 8889)都暴露同样的三个端点。它们回答两个不同的问题,把探针指错位置,就是"平稳度过数据库抖动"与"把抖动升级成一次停机事故"的区别:

端点是否检查数据库用途
/health/liveLiveness 探针
/health/readyReadiness 探针
/healthReadiness——/health/ready的别名,为兼容性保留

/health/live只要进程还能处理请求就返回 200,且不产生任何 I/O:

{ "status": "alive", "version": "0.4.0", "uptime_seconds": 812.4 }

能应答本身就是检查。Hindsight 在单个事件循环上运行请求处理器与任务工作,因此被阻塞调用卡死的事件循环无法在探针超时内应答——而这正是重启能修复的故障类型。其实现位于 liveness.py:模块文档开宗明义地写道"liveness 只回答一个问题:这个进程是否已经卡死到只能靠重启修复?它绝不能触碰数据库",因为"运行SELECT 1的 liveness 探针会把数据库降级变成停机事故"。

worker 的载荷额外增加了worker_idis_shutdownseconds_since_last_poll(距上次完成 claim 周期的时长,第一次之前为null)。最后一个字段是为了告警而设计的:它从不改变状态码,因为卡在饱和数据库后面的 poller 恰恰是"重启会雪上加霜"的情形——正如 WorkerLivenessResponse 的文档所写:"报告它只是为了告警——无论它多陈旧端点都保持 200,这样饱和的数据库永远不可能触发重启。"

/health/health/ready获取一个池化连接并执行SELECT 1,数据库可达时返回 200,不可达时返回 503。载荷区分了两种出错方式——db_acquire_msdb_pool_waiting指向连接池耗尽,而慢查询指向数据库本身:

{ "status": "healthy", "database": "connected", "db_acquire_ms": 0.4, "db_pool_waiting": 0 }

:::warning 绝不要把 liveness 探针指向依赖检查 liveness 失败意味着"重启这个进程"。如果 liveness 探针检查数据库,那么数据库变慢会让所有 Pod 同时重启:在途请求被丢弃,已认领的异步操作以递增的retry_count重新排队,一步步走向永久失败悬崖;每个重启的 Pod 还会在一个已经不堪重负的数据库上重新连接、重新预热连接池。就绪失败才是正确响应——它把 Pod 从 Service 中摘除,待数据库恢复后再放回。

仓库自带的 Helm chart 已经如此配置(livenessProbe/health/livereadinessProbe/health)。如果你基于旧版本手写了 manifest,请把 liveness 路径改过来。 :::

这条警告在源码与 Helm 配置中都能得到印证:api-deployment.yaml 将探针模板化为 values 中的值,而 values.yaml 中 API 的livenessProbe使用httpGet: path: /health/live, port: 8888initialDelaySeconds: 30, periodSeconds: 10, timeoutSeconds: 5, failureThreshold: 3),readinessProbe使用path: /healthinitialDelaySeconds: 10, periodSeconds: 5, timeoutSeconds: 3, failureThreshold: 3)。注释还特别说明 liveness 需要 chart 的 appVersion 或更新版本的镜像——旧镜像只提供/health,会以 404 使探针失败。worker(端口 8889)的探针配置同样遵循这一模式。

指标端点与指标体系概览

Hindsight 在/metrics暴露 Prometheus 指标:

curl http://localhost:8888/metrics

指标基于 OpenTelemetry SDK 构建,由 metrics.py 中的initialize_metrics()完成初始化:创建带service.name/service.version资源的MeterProvider,通过PrometheusMetricReader导出,并为三个时长直方图注册自定义分桶的 View(见下文"直方图分桶")。MetricsCollector类通过create_histogram/create_counter/create_up_down_counter/create_observable_gauge逐一注册了本文列出的全部指标;当指标未启用时,NoOpMetricsCollector提供同接口的空实现,保证调用方无需判空。

指标体系中还有几个仓库实现中值得一提的细节:

  • 租户标签:所有核心指标都通过_get_tenant()附带tenant标签(来自当前 schema),多租户部署可按租户拆分查询(原文档表格未列出,但源码确认存在);
  • 端点基数控制:normalize_http_endpoint() 会把路径中的/banks/<id>段、UUID 和纯数字 ID 分别模板化为{bank_id}{id},保证endpoint标签基数有界;
  • 指标开关metrics_include_bank_id配置项控制是否附加bank_id标签(避免高基数);
  • 同步抓取路径:backlog / 队列深度等 gauge 由后台任务每 30 秒刷新缓存,/metrics抓取路径保持同步(见 metrics.py)。

指标详解

操作指标(Operation Metrics)

指标类型标签说明
hindsight.operation.durationHistogramoperation, bank_id, source, budget, max_tokens, success操作时长(秒)
hindsight.operation.totalCounteroperation, bank_id, source, budget, max_tokens, success已执行操作总数

标签:

  • operation:操作类型(retainrecallreflect,以及consolidation等异步 worker 任务类型)
  • bank_id:记忆银行标识
  • source:操作触发来源(apireflectinternalworker
  • budget:若指定则为预算等级(lowmidhigh
  • max_tokens:若指定则为最大 token 数
  • success:操作是否成功(truefalse

source标签用于区分:

  • api:客户端直接 API 调用
  • reflect:reflect 操作期间发起的内部 recall 调用
  • internal:其他内部操作
  • worker:异步 worker 在认领任务达到终态时记录的完成

对于source="worker"success标签是完成吞吐信号:false表示任务在重试耗尽或发生意外错误后向 poller 抛出。在 executor 内部处理并正常返回的失败在此仍记录success="true";要获取权威的异步操作失败状态,请使用hindsight_async_operations{status="failed"}

从源码看,操作指标还隐藏了一个语义细节:在 record_operation 的上下文管理器中,客户端断连导致的取消(OperationCancelledError,由 HTTP 层以HTTPException(499)重新抛出)既不算成功也不算失败,会被完全排除在指标之外,避免膨胀成功率或失败率——这是通过遍历__cause__链匹配取消异常实现的(见_is_client_cancellation)。

Retain 指标

指标类型标签说明
hindsight.retain.documents.totalCounteroutcome, bank_idretain 处理的文档数,按抽取结果分桶

标签:

  • outcome:文档在 retain 后拥有记忆单元时为facts,没有则为no_facts
  • bank_id:记忆银行标识

outcome="no_facts"是"文档已存储但未产生任何记忆"的信号。这些文档对recallreflect不可见,直到被重新处理——没有其他指标会报告它们,因为 retain 本身成功了。该占比上升通常意味着 retain mission 排除了超出预期的内容:

sum(rate(hindsight_retain_documents_total{outcome="no_facts"}[15m])) / sum(rate(hindsight_retain_documents_total[15m]))

这一指标的动机在 metrics.py 的注释中有明确记录:"只有 memory_units 携带嵌入,文档零事实意味着它在 recall/reflect 中不可达,而系统内没有任何其他东西报告它——操作仍然成功完成。对它告警可以捕捉到 retain_mission 静默排除过多内容(issue #3040)。"

LLM 指标

指标类型标签说明
hindsight.llm.durationHistogramprovider, model, scope, successLLM API 调用时长(秒)
hindsight.llm.calls.totalCounterprovider, model, scope, successLLM API 调用总数
hindsight.llm.tokens.inputCounterprovider, model, scope, success, token_bucketLLM 调用输入 token
hindsight.llm.tokens.outputCounterprovider, model, scope, success, token_bucketLLM 调用输出 token

标签:

  • provider:LLM 提供商(openaianthropicgeminigroqollamalmstudiobedrocklitellm
  • model:模型名(如gpt-4claude-3-sonnet
  • scope:LLM 调用的用途(memoryreflectconsolidationanswer
  • success:调用是否成功(truefalse
  • token_bucket:用于基数控制的 token 数分桶(0-100100-500500-1k1k-5k5k-10k10k-50k50k+

token_bucket的实现就是 get_token_bucket():把连续 token 数映射到 7 个离散桶,避免每个调用产生一个唯一标签值而引发高基数问题。

此外,源码中还注册了两个原文档未列入表格的补充计数器,用于更诚实的成本归属:

  • hindsight.llm.tokens.cached_input:按缓存费率计费的输入 token 子集,用于独立追踪提示缓存命中率;
  • hindsight.llm.tokens.thoughts:推理/思考 token(Gemini 2.5+ 系列),按输出费率计费但不出现在 candidates 中——"按输出量看起来便宜、实际因长推理链而昂贵"的工作负载正是靠它暴露的。

合并指标(Consolidation Metrics)

指标类型标签说明
hindsight.consolidation.batch_failuresCounterfailure_class, error_type失败的合并 LLM 批量调用,包括其事实后来被恢复的

标签:

  • failure_class:调用的处理方式(fail_fast——模型返回了响应 schema 拒绝的内容,重发相同载荷无济于事;retry——传输层形态的问题,原样重发可能成功;propagate——不属于批量失败,重新抛给任务处理器)
  • error_type:异常类名(如ValidationErrorJSONDecodeError

这与 bank stats 中的failed_consolidation字段不是同一个信号。该字段统计的是失败后仍在等待合并的事实;当批量调用失败时,合并会把批次减半重试,因此一个在批次大小 8 时失败、大小 1 时成功的调用会让failed_consolidation停留在 0。但失败响应请求的一切都会被丢弃——包括它想删除的 observations——所以一个银行可以看起来完全健康,而其超驰清理却什么都没做。

对 schema 拒绝率告警,这是其他指标无法暴露的:

sum(rate(hindsight_consolidation_batch_failures_total{failure_class="fail_fast"}[15m]))

持续非零的速率通常意味着合并模型不能稳定地为响应 schema 输出合法 JSON。切换到结构化输出更强的模型,或在提供商支持语法强制的 schema 时启用HINDSIGHT_API_LLM_STRICT_SCHEMA_CONSOLIDATION,是常见的修复方式。

同一计数还会按运行周期报告为合并操作结果中的llm_batch_failures,合并日志摘要会在其非零时打印警告行。两者统计的都是尝试次数——一个重试三次的批量调用贡献三次——因此不受运行中批次数量上限的约束。

源码注释(metrics.py)进一步阐明了设计动机:"failed_consolidation是对携带consolidation_failed_at的行的 gauge,因此它只报告卡住的事实——绝不会报告失败后其事实被调用方的自适应二分法救回的调用。一次运行可以烧掉几十次 schema 非法的调用、丢弃它们携带的全部删除,却仍以该 gauge 为 0 和observations_deleted为 0 结束,与健康运行无法区分(#4151、#4152)。这个计数器正是缺失的信号:它统计调用,而非卡住的行。"

HTTP 请求指标

指标类型标签说明
hindsight.http.durationHistogrammethod, endpoint, status_code, status_classHTTP 请求时长(秒)
hindsight.http.requests.totalCountermethod, endpoint, status_code, status_classHTTP 请求总数
hindsight.http.requests.in_progressUpDownCountermethod, endpoint正在处理的 HTTP 请求数

标签:

  • method:HTTP 方法(GETPOSTPUTDELETE
  • endpoint:请求路径(已归一化以降低基数——UUID 替换为{id}
  • status_code:HTTP 状态码(200400500等)
  • status_class:状态码类别(2xx4xx5xx

HTTP 指标由 observability.py 中的纯 ASGI 中间件HttpObservabilityMiddleware记录。该文件的文档字符串解释了一个重要的性能背景:它取代了两个基于@app.middleware("http")的 StarletteBaseHTTPMiddleware处理器——后者每次请求都会派生子任务并通过 anyio 内存流管道传输响应,在 2-CPU 容器、32 并发客户端的实测中,移除它们使/health/live从约 1500 rps 提升到约 5100 rps(p99 从 159ms 降到 33ms),同时 CPU 从饱和的单核降到约 65%——成本来自调度跳转而非计算。纯 ASGI 中间件则是在同一任务中的一次await,包裹send以观察响应,同时负责把未知参数注入X-Ignored-Params响应头。

数据库连接池指标

指标类型标签说明
hindsight.db.pool.sizeGauge-连接池当前连接数
hindsight.db.pool.idleGauge-连接池空闲连接数
hindsight.db.pool.minGauge-连接池最小大小
hindsight.db.pool.maxGauge-连接池最大大小

(源码中还存在hindsight.db.pool.acquire_wait直方图,用于记录等待获取池化数据库连接的时间——即连接池耗尽信号;以及hindsight.event_loop.stalls/hindsight.event_loop.stall_duration,用于检测超过 watchdog 阈值的事件循环停滞,来自 loop_watchdog.py。)

进程指标

指标类型标签说明
hindsight.process.cpu.secondsGaugetype进程 CPU 时间(秒)
hindsight.process.memory.bytesGaugetype进程内存使用(字节)
hindsight.process.open_fdsGauge-打开的文件描述符数
hindsight.process.threadsGauge-活跃线程数

标签:

  • type(CPU):usersystem
  • type(内存):rss_max(最大常驻集大小)

进程指标以可观测 gauge 实现,在抓取时通过回调采集:CPU 时间来自getrusageru_utime/ru_stime,内存使用ru_maxrss(源码注释提醒:Linux 上该值以 KB 计,需乘以 1024 转字节,而 macOS 上本身就是字节);open_fds在 Linux 上通过枚举/proc/self/fd计数,否则回退到资源软限制;threads使用threading.active_count()(见 metrics.py)。

直方图分桶

为获得更准确的分位数,配置了自定义桶边界:

操作时长分桶(秒):

0.1, 0.25, 0.5, 0.75, 1.0, 2.0, 3.0, 5.0, 7.5, 10.0, 15.0, 20.0, 30.0, 60.0, 120.0

LLM 时长分桶(秒):

0.1, 0.25, 0.5, 1.0, 2.0, 3.0, 5.0, 10.0, 15.0, 30.0, 60.0, 120.0

HTTP 时长分桶(秒):

0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, 30.0

这三组分桶常量直接定义在 metrics.py,并通过ExplicitBucketHistogramAggregation视图在初始化时注册:操作桶在 0–30 秒区间(大多数操作完成的范围)提供细粒度,LLM 桶针对更快的调用细化,HTTP 桶则细化到毫秒级以覆盖快速端点。

Prometheus 抓取配置

scrape_configs: - job_name: 'hindsight' static_configs: - targets: ['localhost:8888']

生产抓取时,参考 scripts/dev/monitoring/prometheus.yml 中现成的写法:metrics_path: '/metrics'、5 秒抓取间隔、单独为 worker 增加一个 job(目标端口 8889),并按需开启scrape_native_histograms

示例 PromQL 查询

按类型统计平均操作延迟

rate(hindsight_operation_duration_sum[5m]) / rate(hindsight_operation_duration_count[5m])

各提供商每分钟 LLM 调用数

rate(hindsight_llm_calls_total[1m]) * 60

P95 LLM 延迟

histogram_quantile(0.95, rate(hindsight_llm_duration_bucket[5m]))

按模型统计总 token 消耗

sum by (model) (hindsight_llm_tokens_input_total + hindsight_llm_tokens_output_total)

内部 vs API recall 操作

sum by (source) (rate(hindsight_operation_total{operation="recall"}[5m]))

按端点统计每秒 HTTP 请求数

sum by (endpoint) (rate(hindsight_http_requests_total[1m]))

HTTP 错误率(5xx)

sum(rate(hindsight_http_requests_total{status_class="5xx"}[5m])) / sum(rate(hindsight_http_requests_total[5m]))

P95 HTTP 延迟

histogram_quantile(0.95, sum by (le) (rate(hindsight_http_duration_seconds_bucket[5m])))

数据库连接池利用率

hindsight_db_pool_size / hindsight_db_pool_max

活跃数据库连接数

hindsight_db_pool_size - hindsight_db_pool_idle

CPU 使用率

rate(hindsight_process_cpu_seconds{type="user"}[1m])

Grafana 仪表盘

预置仪表盘位于 monitoring/grafana/dashboards/,包含三个 JSON 文件:hindsight-operations.jsonhindsight-llm.jsonhindsight-api-service.json。将它们导入 Grafana 实例即可:

仪表盘说明
Hindsight Operations操作速率、延迟分位数、按银行统计的指标
Hindsight LLM MetricsLLM 调用、token 使用、按 scope/提供商统计的延迟
Hindsight API ServiceHTTP 请求、错误率、数据库连接池、进程指标

使用监控栈脚本时,仪表盘会通过 grafana-dashboards.yaml 自动 provisioning——该文件先声明 LGTM 自带的 RED Metrics(classic 与 native 直方图)与 JVM Metrics 仪表盘,随后声明三个 Hindsight 仪表盘(foldersFromFilesStructure: false,全部放在根目录)。

分布式追踪

Hindsight 支持针对记忆操作与 LLM 调用的 OpenTelemetry 分布式追踪,遵循 GenAI 语义约定 v1.37+。追踪由 tracing.py 实现:默认关闭(与DEFAULT_OTEL_TRACES_ENABLED = False对应,见 config.py),启用时通过 OTLP HTTP 导出器导出到任意兼容后端。

配置

环境变量见 Configuration - OpenTelemetry Tracing(表格摘录):

环境变量说明默认值
HINDSIGHT_API_OTEL_TRACES_ENABLED为 LLM 调用启用分布式追踪false
HINDSIGHT_API_OTEL_EXPORTER_OTLP_ENDPOINTOTLP 端点 URL(如 Grafana LGTM、Langfuse 等)-
HINDSIGHT_API_OTEL_EXPORTER_OTLP_HEADERSOTLP 导出器请求头(格式:"key1=value1,key2=value2"-
HINDSIGHT_API_OTEL_SERVICE_NAME追踪的服务名。适用于 API 与独立 worker——未设置时 worker 默认上报为hindsight-workerhindsight-api
HINDSIGHT_API_OTEL_DEPLOYMENT_ENVIRONMENT部署环境名(如 development、staging、production)development

快速开始:

# 启用追踪 export HINDSIGHT_API_OTEL_TRACES_ENABLED=true export HINDSIGHT_API_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 # 使用 Grafana LGTM 查看追踪(本地开发) ./scripts/dev/start-monitoring.sh # 打开 http://localhost:3000 → Explore → Tempo

支持任何 OTLP 兼容后端(Grafana LGTM、Langfuse、OpenLIT、DataDog、New Relic、Honeycomb、Pydantic Logfire 等)。

从实现细节看,initialize_tracing() 会自动为不以/v1/traces结尾的端点补上该路径后缀,解析"key1=value1,key2=value2"格式的请求头,并使用BatchSpanProcessor批量导出;initialize_tracing_from_config()保证 API(FastAPI 生命周期)与独立 worker 两个进程入口走同一套初始化逻辑,让设置了HINDSIGHT_API_OTEL_*的部署能从每个干活的进程拿到追踪(issue #3614),且初始化失败只记录日志、绝不让进程无法启动——"tracing 绝不能阻碍进程启动"。shutdown_tracing()会强制冲刷BatchSpanProcessor,避免进程退出时丢弃仍在队列中的 span——这对单条合并 span 可能长达数分钟的 worker 尤其重要。

Span 层级

父 Span(操作):

  • hindsight.retain- 记忆摄取
  • hindsight.recall- 记忆检索
    • hindsight.recall_embedding- 查询嵌入
    • hindsight.recall_retrieval- 并行搜索(语义、BM25、图、时间)
    • hindsight.recall_fusion- 倒数排名融合(RRF)
    • hindsight.recall_rerank- 交叉编码器重排
  • hindsight.reflect- 智能体推理
    • hindsight.reflect_tool_call- 工具执行(recall、lookup 等)
  • hindsight.consolidation- 观察综合
  • hindsight.mental_model_refresh- 心智模型更新

子 Span(LLM 调用):

  • 按 scope 命名(如hindsight.memoryhindsight.reflect
  • 以事件形式包含完整提示词/补全
  • 属性遵循 GenAI 语义约定

父操作 span 由 create_operation_span() 创建,命名规则为hindsight.{operation}并设置hindsight.operationhindsight.bank_id属性。LLM 子 span 由LLMSpanRecorder.record_llm_call()在调用完成后以显式时间戳创建(end_on_exit=False+ 手动span.end()),以适配现有的同步指标记录模式。

Span 属性

操作 Span:

  • hindsight.operation- 操作类型
  • hindsight.bank_id- 记忆银行 ID
  • hindsight.query- 查询文本(截断到 100 字符)
  • hindsight.fact_types- recall 的事实类型
  • hindsight.thinking_budget- 预算分配
  • hindsight.max_tokens- token 上限

LLM Span(GenAI 语义约定):

  • gen_ai.operation.name- 恒为"chat"
  • gen_ai.provider.name- 提供商(openaianthropicgoogle等)
  • gen_ai.request.model- 模型名
  • gen_ai.usage.input_tokens- 输入 token
  • gen_ai.usage.output_tokens- 输出 token
  • hindsight.scope- LLM 调用用途(memoryreflectconsolidation等)

事件:

  • gen_ai.client.inference.operation.details- 完整提示词与补全

在实现中,提供商名通过PROVIDER_NAME_MAPPING映射为 GenAI 语义约定的值(如geminigoogleopenai-codexopenai),消息以 JSON 数组写入事件属性,超长内容截断到MAX_CONTENT_LENGTH = 100_000字符并附截断说明;工具调用会记录gen_ai.tool_calls.count/gen_ai.tool_calls.names属性与逐条gen_ai.tool_call.{i}事件;出错时设置错误状态、error.type属性并调用record_exception。此外,CompositeSpanRecorder会把同一 LLM 调用扇出给所有注册的 recorder(如 OpenTelemetry span 导出器与按银行落库的 DB tracer),单个 recorder 失败绝不影响其他 recorder 与 LLM 调用本身。

追踪上下文传播

Hindsight 会融入你已有的追踪,而不是另起一套并行的追踪。当调用方发送 W3C 追踪上下文(标准的traceparent头,大多数 OpenTelemetry HTTP 客户端插桩都会自动添加)时,Hindsight 会继续该追踪:API 请求作为调用方下的一个 server span 出现,其触发的每个记忆操作与 LLM 调用都嵌套在其下。

没有携带追踪上下文的请求仍然会开启自己的追踪,因此未插桩的调用方行为不变。

健康与指标端点被排除在追踪之外,这样探针流量不会淹没真正的工作。可通过OTEL_PYTHON_FASTAPI_EXCLUDED_URLS设置为逗号分隔的 URL 模式列表来覆盖此行为(默认值为health,metrics,见 configuration.md)。

值得一提的实现细节是,异步任务队列与追踪的打通:inject_task_trace_context()会把当前 W3C traceparent 写入任务 payload(键为_traceparent),worker 侧再由extract_task_trace_context()重建出队时请求的追踪上下文并包裹任务执行——否则 API 的 enqueue span 与 worker 的hindsight.retainspan 就是两条互不相干的追踪,API 那半条里只有入队动作。

Worker 进程

独立 worker 进程遵循与 API 相同的HINDSIGHT_API_OTEL_*变量并导出自己的 span。这对部署了专用 worker 的环境很重要,因为合并、后台 retain 与心智模型刷新——大部分长时工作与 token 开销——都发生在那里。

为 worker 设置独立的HINDSIGHT_API_OTEL_SERVICE_NAME,以便在追踪后端中将其与 API 区分。未设置时,worker 默认上报为hindsight-worker

worker 的 span 目前是独立的追踪:后台操作不会链接到将其入队的请求,因为它在该请求返回后很久才执行。

小结

把本文的要点压缩成一份可操作的核对清单:

  1. 本地开发./scripts/dev/start-monitoring.sh一条命令拉起 Grafana LGTM,通过HINDSIGHT_API_OTEL_TRACES_ENABLED=true+HINDSIGHT_API_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318启用追踪;
  2. 健康探针:liveness 永远指向/health/live(零 I/O),readiness 指向/healthSELECT 1检查数据库);seconds_since_last_poll只用于告警、永不改变状态码;
  3. 指标告警no_facts占比告警监控 retain mission 过度排除;failure_class="fail_fast"告警捕获 schema 拒绝导致的静默清理失效;hindsight.operation.total{source="worker",success="false"}hindsight_async_operations{status="failed"}组合使用以获得权威的异步失败;
  4. 追踪:API 与 worker 共用一套HINDSIGHT_API_OTEL_*配置,为 worker 单独命名服务以区分;生产环境务必调用shutdown_tracing()冲刷 span,避免丢失长 span。

仓库中的三个仪表盘 JSON、prometheus.yml抓取模板与 Helm 探针配置都可以直接作为生产部署的起点。

【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询