OpenAI 与 V7:用「上下文图谱」给 Agent 装上机构记忆

·阅读约12分钟·Evergreen Tools Team

今天的模型很会推理,但它们并不自动理解任务背后的业务上下文。「哪一份基金报告才是最新的?」「同一个实体在三个系统里到底叫什么名字?」这些问题的答案散落在文档、数据室、表格、邮件和内部工具里——零散、未对齐,而且对 Agent 完全不可见。2026 年 9 月 21 日,OpenAI 发布了一篇客户案例,讲的正是这件事:V7 的 Go 平台用一张「上下文图谱(Context Graph)」把公司文件变成 Agent 可以查询和行动的上下文。最值得记住的不是某个模型分数,而是那句总结:「真正从 AI 拿到价值的金融公司,不会是 Agent 最多的那批,而是上下文最好的那批。」

文档与数据室

上下文藏在文档、表格和邮件里,对 Agent 不可见

一、真正的成本:每次请求都重新找一遍上下文

大多数 Agent 架构的默认行为是「无状态 + 每次重查」。用户提一个问题,Agent 就去 SharePoint 搜一遍、去 Drive 搜一遍、再去邮件里搜一遍,然后把命中片段一股脑塞进提示词。这在演示里没问题,在生产里是三笔账:第一,每次请求都重复几十次搜索,时间和 token 都按请求量线性增长;第二,你只看到文本,看不到关系——「这份 CIM 里的基金」和「三年前那份托管协议里的同一个基金」之间的关系,永远不会被拼接起来;第三,也是最隐蔽的一笔,模型每次都在重新学习你的业务,昨天刚建立的理解,今天全部清零。

// The expensive default: every request rediscovers context.
async function naivelyAnswer(question) {
  const hits = [];
  hits.push(...await search("sharepoint", question));
  hits.push(...await search("drive", question));
  hits.push(...await search("email", question));   // dozens of searches...
  const prompt = hits.map((h) => h.text).join("\n");  // ...all stuffed into context
  return llm.ask(prompt, question);
}
// Cost grows with every request, and relationships between files are
// invisible because you only ever see text, never the edges.

二、Context Graph:把「关系」变成一等公民

V7 Go 的做法是先把上下文结构化。新数据到达时,它连接 SharePoint、Google Drive 这类仓库,扫描其中的实体、关系、事实、属性和指标,然后填充一张图。官方说法是,遍历这张图的成本与速度比「长上下文」方案好一个数量级。关键设计有三个:其一,事实与出处绑定——每条记录都保留指向原始文件的引用证据,这让下游的每一步都能被审计;其二,图谱查询与 RAG 兜底并存——当图谱里没有足够信息时,仍然回退到对原始文档的检索;其三,增量更新——新文件到达时识别其中的公司、基金、人,并挂到已有记录上,而不是重建整张图。更根本的一点是:模型可以在不了解你公司历史的情况下工作,而图谱让它可以「不必每次重新学一遍」。

# Build a canonical key before you build a graph.
# "Acme Fund III LP", "ACME FUND III, L.P." and "Acme III" must be one node.
import re, unicodedata

SUFFIX = {"lp", "llc", "inc", "ltd", "fund", "iii", "ii", "i"}

def canonical(name: str) -> str:
    s = unicodedata.normalize("NFKD", name).lower()
    s = re.sub(r"[^a-z0-9 ]", " ", s)
    tokens = [t for t in s.split() if t and t not in SUFFIX]
    return " ".join(tokens)

print(canonical("Acme Fund III, L.P."))   # -> "acme"
print(canonical("ACME FUND III LP"))      # -> "acme"

三、数字:从 HERB 基准到最难图谱查询

V7 测试过「结构」到底值多少钱。在 HERB 这个衡量跨企业系统信息发现与连接的基准上,V7 仅做检索的系统比官方基线高 69%,并且把「不可回答查询」上的幻觉降低了 38%。在生产路径上,他们说 Agent 能在几分钟内跑完 50 到 100 步的工作流,达到 99.9% 的准确率,同时保留每一步决策的可审计轨迹。模型方面则是分级路由:高频结构化抽取交给 GPT-5.6 Luna,推理与工具使用交给 GPT-5.6 Terra 或 Sol,只有最难的图谱查询才用 GPT-6 Astra。在 V7 自建的四级难度图谱问题集上,很硬那一档里 GPT-5.6 Sol 得分 78%,GPT-6 Astra 得分 89%,而两种模型在简单、中等、困难三档都接近满分——也就是说,前沿模型的溢价应该只花在这条窄带上。此外,把文档密集负载从 Chat Completions 迁到 Responses API,让部分 PDF 密集工作流的 token 用量下降了约 5%,并改善了缓存可靠性。

// Populate the graph on arrival, and keep the evidence link.
async function ingest(file) {
  const extracted = await model.extract(file.text, ONTOLOGY);

  for (const fact of extracted.facts) {
    const node = await graph.upsertEntity({
      type: fact.entityType,
      key: canonical(fact.entityName),
      attributes: fact.attributes,
    });

    await graph.addFact(node.id, fact.predicate, fact.value, {
      sourceUrl: file.url,        // link every fact back to its origin
      page: fact.page,
      extractedAt: new Date().toISOString(),
      model: "gpt-5.6-luna",
    });
  }
}
// If the graph has no answer, fall back to RAG over the raw documents.

四、业务侧的结果长什么样

这些工程决策最终会变成业务数字。资产管理团队筛项目的速度比过去快 21 倍,一整天的工作压缩到 15 分钟;一个金融服务团队把审阅时间从 100 多个小时降到 10 小时以内,每个任务省下 12,000 美元的专家成本;保险团队在让 Agent 掌握历史理赔与既有保单之后,理赔处理错误率相对人工基线下降了 13.5%。这些数字的共同点是:它们都不来自「换个更强的模型」,而来自「让模型拿到对的上下文」。

# Route by difficulty instead of defaulting to the frontier model.
# V7's tiers: GPT-5.6 Luna for high-volume extraction, Terra/Sol for
# reasoning and tool use, GPT-6 Astra only for the hardest graph queries.
TIERS = [
    ("gpt-5.6-luna",  lambda q: q.kind == "extract"),
    ("gpt-5.6-terra", lambda q: q.kind == "reason"),
    ("gpt-6-astra",   lambda q: q.graphComplexity == "very_hard"),
]

def pick_model(query):
    for model, matches in TIERS:
        if matches(query):
            return model
    return "gpt-5.6-sol"

# On V7's hardest benchmark set, GPT-6 Astra scored 89% while the
# previous default scored 78% - a 11-point gain worth paying for
# on this narrow slice, and not on every call.

五、你自己怎么搭:可复用的五步

第一,先做实体归一化,再做图谱。把「Acme Fund III LP」「ACME FUND III, L.P.」和「Acme III」映射到同一个键上,否则图会碎成一地散点。第二,入库时必须绑定出处——每条事实都要能回指原始文件与页码,这是让审计和信任成立的前提。第三,增量更新,而不是重建。第四,分级路由,把前沿模型留给最窄的高难切片。第五,控制上下文预算:最近的对话留在活动上下文里,更老的材料进图谱按需检索。V7 还把图谱查询与写入通过 MCP 服务器暴露出去,客户可以在 ChatGPT 里用,也可以在 Codex 里用 MCP 创建工作流——这让一个中等长度工作流的搭建时间从大约 1 小时降到约 20 分钟。

# Context budget: keep recent turns live, push the archive to the graph.
MAX_LIVE_TURNS = 12
MAX_TOKENS = 60_000

async function assembleContext(session, question) {
  const recent = session.messages.slice(-MAX_LIVE_TURNS);
  const recalled = await graph.query(question, { limit: 40 }); // source-linked

  const ctx = [
    ...recalled.map((f) => `[${f.sourceUrl}] ${f.statement}`),
    ...recent.map((m) => `${m.role}: ${m.content}`),
  ];

  const tokens = countTokens(ctx);
  if (tokens > MAX_TOKENS) {
    // Drop the cheapest-utility evidence first, never the citation.
    return trimByUtility(ctx, MAX_TOKENS);
  }
  return ctx;
}

六、清单与那个更长期的方向

四个检查项。第一,你的 Agent 每次请求是不是都在重复搜索同一批数据?如果是,先测量它浪费了多少 token。第二,你的每条事实有没有出处链接?没有出处的上下文,在受监管行业里等于负债。第三,你有没有把模型路由按难度分层,还是所有请求都打给最贵的那个?第四,你的「记忆」是可查询的结构,还是一坨没人敢删的历史消息?V7 给出的长期方向是让共享记忆变得主动:当图谱里的事实发生变化时,工作流自动启动、标记不一致、指出哪些分析需要重做——比如一份基金报告被重述了,系统会主动揪出仍在使用旧数字的工作。这才是「机构记忆」和「聊天历史」的区别:前者会主动提醒你,后者只会安静地过期。

图谱化的数据关系

把关系变成一等公民,检索成本低一个数量级

模型分级路由

前沿模型的溢价,只花在最难的那条窄带上

📌 常见问题 FAQ

Context Graph 和 RAG 有什么区别?

RAG 每次检索都是一次性的文本拼接,而 Context Graph 把实体、关系和事实持久化,并让每条事实都带着指向原始文件的出处证据;遍历图的成本比长上下文方案低一个数量级,并且图谱不足时仍可回退到 RAG。

为什么说「每次请求重新找上下文」是真正的成本?

因为 Agent 是无状态循环:每个请求都会重复几十次搜索,把命中片段塞进提示词,时间和 token 都随请求量线性增长,而且模型每次都在重新学习你的业务。

GPT-6 Astra 的那 89% 是怎么来的?

在 V7 自建的四级难度图谱问题集上,最难的「very hard」档位里 GPT-5.6 Sol 得分 78%,GPT-6 Astra 得分 89%;在简单、中等、困难三档两者都接近满分。这说明前沿模型的收益集中在最难的窄带上。

该用哪个模型跑哪件事?

高频结构化抽取用 GPT-5.6 Luna(相对 GPT-5.4 mini 单文档成本降低 78%、准确率提升 11.6 个百分点),推理与工具使用用 GPT-5.6 Terra 或 Sol,只有最难的图谱查询才上 GPT-6 Astra。

最容易被忽略的一步是什么?

实体归一化。在做图谱之前先把同一实体在不同系统里的不同写法映射到同一个键,否则图会碎成一堆互不相连的散点,跨文件的关系永远拼不起来。