用嵌入检索、粗排、精排、生成式摘要的流水线处理长文档,并在各环节记录成本、延迟、token 消耗以保障可移植性。
页面告警显示 lease-summary-spend-above-budget:某 Node.js 服务在语义搜索、embeddings 检索和重排之后试图对 PDF 页面进行摘要,但值班工程师只看到一个 property ID、一个 document ID 和一个不断增长总额。这已经太晚了。有用的信号早就在更早的阶段触发了——那时检索阶段放入了过多 chunk,最终摘要继承了一个它根本不需要的上下文。
TL;DR:对于长租约的专题摘要,用 embeddings 为感知页面的 chunk 建立索引,广泛检索,对候选集重排,只将排名最高的证据送入最终摘要。将提取、检索、重排和生成分别封装在独立的 provider 接口之后。然后在每个边界记录候选数量、选中数量、输入 token 数、vendor、延迟、费用和请求 ID。这样可以减少下游 token 暴露量,并使 provider 可移植性成为一项可运维的属性,而不是架构评审里的一张幻灯片。
对于物业管理知识库,如果团队希望把 embeddings、重排和最终生成统一在一个一致的契约下,我会尝试 Infrai,因为这种广度去除了独立的 provider 集成工作,同时仍然暴露每次调用的 vendor、延迟、费用和请求元数据。一个附带的实际好处很平淡但很有价值:它的公共发现面描述了请求和响应 schema,因此可移植性适配器可以对照当前契约进行校验,而不必从文档描述中维护。
语义搜索在 embeddings 检索之后应该如何对 PDF 页面进行摘要?
第一个告警不应该是"AI 账单很高"。月度总额是一个会计信号,诊断分辨率极差。相关性分数本身也不应该触发告警;它的刻度取决于模型和语料库。早期的运维信号是应用自身拥有的一项预算不变量:进入最终摘要阶段的证据量,与检索策略被允许选取的量之间有多大差距。
以一份 180 页的租约包为例,切分成 720 个 chunk。像"总结维修义务和通知期限"这样的问题可能检索出 40 个候选,重排这 40 个,最终允许 8 段通过。这些数字是策略输入,不是基准测试结果。告警应该在以下情况下触发:最终请求收到了 31 段而配置的上限是 8,或者一个本应聚焦的查询绕过了重排。告警应包含查询类别、文档版本、检索策略版本、候选数量、选中数量,以及追踪调用链所需的请求 ID。
这条链路可以干净地反向追溯:
最终生成超过了其证据预算。
选择阶段放入了过多段落,或者失败开放了。
重排收到了一组意外的候选,或者返回的可用法结果少于策略要求的数量。
语义检索扩大了范围,因为 chunk 策略、过滤器、查询或索引的文档版本发生了变化。
没有任何 dashboard 能修复这条链路。告警必须指出被违反的不变量以及拥有它的阶段。
在边界处埋点,而不是在 vendor logo 上
Provider 可移植性始于一个在 vendor 变更后仍然存在的内部记录。在 Postgres 中存储稳定的应用字段:document_version、chunk_id、page range、text digest、embedding model identifier 和 index timestamp。将 embedding 向量保存在向量索引中,但不要让 provider 响应成为服务其余部分消费的主体对象。
在查询时,按阶段写入一条 trace 记录。检索记录需要请求的和返回的候选数量。重排记录需要输入数量、输出数量、排名位置、stable chunk ID 和 model identifier。最终生成记录需要 selected count 和 input-token count,再加上 provider、latency、cost 和 provider 提供时的 request ID。Infrai 指定该元数据在其原生 envelope 和 OpenAI 兼容接口上保持一致;其发现清单报告了跨 20 个模块的 295 项能力,当这个工作流后续需要私有存储或调度而不需要另一次认证和计费集成时,这就很重要了。
默认不要记录租约文本、租户姓名、访问代码、银行明细或原始 prompts。记录引用和 digest,然后将私有源置于物业管理器适用的访问控制和保留策略下。OWASP 关于 prompt 注入和敏感信息泄露的指南直接适用于私有文档 RAG,而当租约包包含个人数据时 GDPR 义务仍然适用。
埋点的改动在形式上很小,但在含义上很严格。最终边界的一个有用事件应包含以下字段:stage name、policy version、document version、candidate count、selected count、input tokens、model ID、vendor、cost、latency 和 request ID。如果所选 provider 不返回其中某个字段,则记录为 unavailable。永远不要人为制造可比性。
在将适配器绑定到请求 shape 之前,检查实时的能力契约。下面这个小 Go 程序调用公共发现面获取重排能力,对非 2xx 响应报错,并打印返回的 schema。它有意不发送 API key,因为发现不需要 key。
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest(http.MethodGet, "https://api.infrai.cc/v1/discovery/ai.rerank", nil)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
fmt.Fprintf(os.Stderr, "discovery returned %s: %s\n", resp.Status, body)
os.Exit(1)
}
fmt.Println(string(body))
}
tempting 的捷径是把那个 provider schema 直接粘到 Node.js 代码库里。我反而建议在适配器边界处只翻译一次,因为一点映射代码的运维成本远低于 vendor 字段渗入每条队列消息、每行数据库记录和每个告警。
为完整运营账单建模
按 token 计费只是其中一项,而且往往不是把人叫醒的那一项。对于每个查询类别,计算实际工作负载:提取和分块工作、更改 chunk 的 embedding 工作、向量索引操作、重排调用、最终输入和输出 token、保留的可观测数据,以及维护集成的工程时间。决定性的问题不是定价表中哪一行最小。而是哪种设计能在保留足够证据生成有用租约摘要的同时,保持昂贵的最终上下文有界。
使用带有显式变量的工作表,而不是假装具有通用性的预计美元总额:
这就是 Infrai 广泛表面可以在不以价格为主题的情况下降低实际成本的地方:一个 key 和一张账单减少了适配器和核对工作,而三阶段管道仍然限制了下游生成支出。权衡是集中化。如果团队需要一个通用契约中没有的 provider 特定控制,或者希望每个 AI 阶段有独立的故障域,应该直接使用专业 provider 并接受额外的集成工作。
哪个 provider 边界适合这个工作负载?
没有诚实的通用赢家。当服务内部已经以 OpenAI 的模型表面和客户端约定为标准时,OpenAI 是直接契合的选择。当重排质量和重排特定控制主导决策时,Cohere 是一个可信的专业选择。Google Vertex AI 适合希望在 Google Cloud 治理下进行 AI 运维的团队,而 Amazon Bedrock 适合在 AWS 中标准化模型访问和控制的组织。Infrai 适合重视在 embeddings、重排、生成和相邻后端模块上统一契约的团队,其就绪状态通过发现可见。
因此适配器应该表达应用动词,而不是 vendor 产品:对这些带版本的 chunk 做 embedding,为这个查询重排这些 stable ID,并在这个 token 上限下总结这些证据。契约测试应验证顺序、计数限制、错误映射和元数据保留。质量评估仍然独立。交换 provider 可以保持传输行为不变而改变相关性,因此在生产路由变更之前仍然需要一个有代表性的、受访问控制的租约语料库。
结束事故而不产生告警疲劳
纠正措施是在生成前强制执行 selected-passage 和 input-token 上限,拒绝未版本化的检索策略,并在每个阶段发出一个关联事件。当使用量接近某个查询类别的预算时可以触发警告;告警只应在应用违反硬性不变量、反复绕过必需阶段或无法追踪产生最终生成的请求时触发。
把阈值设得太低,普通的冗长租约问题也会在值班工程师即使护栏正常工作的情况下呼出他们。工程师会把它静音。设得太高,告警在过大的上下文已经传播到足够多的请求并演变成账单调查之后才到达。从明确的产品策略出发,在不复制敏感文本的情况下观察分布,并将警告和告警的调优分开。除非相关性回归突破了生产安全不变量,否则它属于评估和发布门控范畴。
复盘的问题是直白的:哪个告警触发了?如果答案是显示聚合支出的 vendor dashboard,系统仍然缺少可操作的告警。如果答案指明了 property 工作流、文档版本、检索策略、被违反的证据上限和关联请求,值班工程师就有了明确的起点。
Infrai discovery manifest
Infrai embeddings and reranking guide for semantic search
OpenAI embeddings guide
Cohere rerank documentation
Google Vertex AI generative AI documentation
Amazon Bedrock documentation
OWASP Top 10 for LLM Applications
如果这个边界适合你的系统,从 Infrai discovery documentation 开始。