首页 / 文章

OKF + RAG:一种用于构建可靠AI智能体的混合架构

谷歌的开放知识格式能为人工智能代理提供精确的、带有Git版本号的答案,而RAG则能处理那些杂乱无章的档案。一款小型路由器如何将二者整合到同一个代理中。

发布者:REACTAPP.TOP阅读约 6 分钟1326 词

来源: OKF + RAG: The Ultimate AI Agent Architecture

向人工智能代理询问一个广为人知的事实,它能够流畅作答。但若要求它提供公司的具体客户流失计算公式、内部API的架构或数据库故障转移的操作手册,它可能会给出看似合理但实际上完全是编造的内容。这就是幻觉问题,也是企业不愿将实际工作交给这类代理的主要原因。

过去两年的标准解决方案是RAG:将模型与存储公司文档的向量数据库相连,检索出看似相关的内容并将其插入提示词中。对于大量非结构化文本,这种方法确实有效。但其弱点在于它具有概率性,只会返回在语义上与问题相似的段落,而这与那些具有权威性的内容截然不同。当问题涉及官方的收入计算公式或支付接口的合同条款时,仅靠语义相似性是远远不够的。

2026年6月,Google Cloud推出了开放知识格式(OKF),这是一种针对以Markdown文件形式存储的精选知识的供应商中立规范。将它的精确检索功能与RAG的广泛覆盖能力相结合,便能形成一种架构,非常适合那些既需要精确性又需要探索能力的智能体。

两种记忆机制

想象一下新员工入职的第一天,会有两样东西呈现在他们面前。

第一样是经过整理的内部维基:标准定义、API文档、指标公式以及操作手册,所有内容都经过审核、批准并实行版本控制。当他们需要官方答案时,就会去那里查找。这正是OKF所承担的角色。

第二种则是超越其他所有内容的搜索引擎:涵盖成千上万的聊天记录、邮件往来、支持工单以及会议记录。当他们想要了解人们对某个主题的讨论,或检索非结构化的档案时,就会在那里进行搜索。这就是RAG。

单独使用其中任何一种都不够。将两者结合才能覆盖一个组织所掌握的全部信息。

OKF是什么

OKF的设计风格极为简洁。一个“bundle”其实就是存储在Git中的Markdown文件目录。每个文件描述一个概念,比如表格、指标、API接口或操作手册,并以一段YAML格式的元数据开头,以便机器读取。该规范对创建者几乎没有过多要求,Obsidian、Notion或MkDocs等工具已经能够处理相同格式的文件。该项目托管在公共代码库中。

业务指标的文件在前置信息中可能包含类型、标题、描述、负责人、标签以及时间戳。正文部分则会列出官方公式、若干规则(例如,分母中不包含试用账户,计划降级也不计入流失率),作为数据来源的表格,以及相关概念的链接。

---
type: metric
title: "Monthly Churn Rate"
description: "Official formula for calculating monthly customer churn."
owner: "data-engineering"
tags: [revenue, kpi, board-report]
timestamp: 2026-06-20T10:00:00Z
---

# Monthly Churn Rate

The official churn rate formula used in all board reports and investor decks:

    Churn Rate = (Customers Lost During Month / Customers at Start of Month) × 100

### Rules
- **Do NOT** use trial accounts in the denominator.
- **Do NOT** count plan downgrades as churn.
- Source of truth: `analytics.monthly_churn_summary` table.

### Related
- [Monthly Active Users](mau.md)
- [Revenue Dashboard](revenue_dashboard.md)

为什么要这么做?

  • 无需向量数学运算。当智能体需要流失率计算公式时,它会直接读取该文件。没有嵌入操作、相似度评分或top-k筛选,每次得到的都是预先确定的答案。
  • 与Git工作流深度集成。所有更改都会通过拉取请求、审核流程和提交历史记录来处理,因此可以追溯是谁在何时以及为何修改了公式。
  • 无需额外基础设施。没有向量存储库、嵌入处理流程、分块策略或重新索引任务,文件只需存放在文件夹中即可。

RAG是什么

RAG通过六个步骤将模型与大规模非结构化数据相连:

  1. 导入PDF、邮件、维基页面和聊天消息等文档。
  2. 将这些文档分割成更小的片段。
  3. 使用嵌入模型将每个片段转换为向量。
  4. 将生成的向量存储在Pinecone、Weaviate或pgvector等数据库中。
  • 在查询时,将问题嵌入到同一空间中,进而获取最相似的文本片段。
  • 将这些文本片段加入提示词中,以便模型能够结合上下文给出答案。
  • RAG的优势在于覆盖范围广,它能够从成千上万的文档中提取出相关内容,而这些内容是人工无法整理的。它的劣势在于精确度不高,由于检索是基于相似度进行的,因此可能会返回相关但并非权威的文本。如果三种不同的定义对“用户流失”的表述略有差异,RAG很可能会选择错误的那一种。

    混合设计

    这种组合架构在两种存储方式之前都设置了一个路由器。该路由器会分析每个传入的查询,决定将其发送到何处:如果是关于官方定义的查询,就发送到经过整理的文档集中;如果是开放性且需要探索性的查询,则发送到向量搜索系统中。

    那个路由器的简化版 Python 实现承担四项功能:它加载包中的所有 Markdown 文件,并根据前置信息中的标题为它们建立索引;接着尝试通过确定性关键词匹配将查询与这些标题进行比对;如果找到对应概念,就会将该内容标记为来自官方知识库并传递给模型;否则则转而使用向量搜索(标记为文档搜索),然后将选定的上下文连同“仅依据所提供的内容进行回答”的指令一起发送给模型。在提示词中对来源进行标注非常重要,因为它能告知模型以及后续的读者,该上下文应被赋予多大的权重。

    from openai import OpenAI
    import os
    import glob
    import yaml
    
    client = OpenAI()
    
    # 1. Load the OKF knowledge bundle from the local directory
    def load_okf_bundle(bundle_path: str) -> dict:
        """Reads all Markdown files in the OKF directory into a searchable dict."""
        knowledge = {}
        for filepath in glob.glob(f"{bundle_path}/**/*.md", recursive=True):
            with open(filepath) as f:
                content = f.read()
                # Extract the title from YAML frontmatter
                if content.startswith("---"):
                    _, frontmatter, body = content.split("---", 2)
                    meta = yaml.safe_load(frontmatter)
                    title = meta.get("title", os.path.basename(filepath))
                    knowledge[title.lower()] = body.strip()
        return knowledge
    
    # 2. Search OKF (deterministic, keyword-based)
    def search_okf(query: str, okf_knowledge: dict) -> str | None:
        """Simple keyword match against OKF titles."""
        for title, content in okf_knowledge.items():
            if title in query.lower():
                return content
        return None
    
    # 3. Search RAG (probabilistic, vector-based)
    def search_rag(query: str) -> str:
        """Placeholder for your vector DB search (Pinecone, Weaviate, etc.)."""
        # results = vector_db.similarity_search(query, top_k=5)
        return "RAG context: [retrieved chunks would appear here]"
    
    # 4. The Intelligent Router
    def answer_query(query: str, okf_bundle_path: str) -> str:
        okf_knowledge = load_okf_bundle(okf_bundle_path)
    
        # Try OKF first (deterministic path)
        okf_result = search_okf(query, okf_knowledge)
    
        if okf_result:
            context = f"[SOURCE: Official Knowledge Base (OKF)]\n{okf_result}"
        else:
            # Fall back to RAG (probabilistic path)
            context = f"[SOURCE: Document Search (RAG)]\n{search_rag(query)}"
    
        # Send to LLM with the retrieved context
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=[
                {"role": "system", "content": "Answer using ONLY the provided context."},
                {"role": "user", "content": f"Context:\n{context}\n\nQuestion: {query}"}
            ]
        )
        return response.choices[0].message.content
    

    此处的匹配方式刻意较为简单,仅通过标题检索来让核心思路清晰可见。实际生产系统会采用更完善的路由机制,比如分类器或元数据过滤器,并能处理两个数据源都返回相关内容的情况。

    核心要点

    对于企业级智能体而言,并不存在必须在OKF和RAG之间二选一的问题。最佳设计是同时使用两者:由Git控制的确定性知识库可用于保护那些绝不能出错的要素,如KPI、API协议和操作手册;而概率向量搜索则可处理那些无人能进行筛选的大量非结构化资料。这样一来,智能体在需要精确结果时能做到精准无误,在需要探索性结果时则能发挥探索功能。