从 0 到 1 构建企业级智能知识库 Agent:NextKB 架构设计与落地实战
技术栈:Google ADK · Vertex AI Reasoning Engine · Gemini · Vertex AI Search · FastAPI · Cloud Run · GCS · Document AI
企业内部文档通常并不缺,缺的是能理解工程意图、能给出可执行步骤、还能把每一句结论指回权威文档的问答系统。关键词搜索解决不了多轮上下文;通用大模型又容易幻觉。NextKB 的目标就是把这两件事一起做掉:用企业私有知识库做 RAG,用 Agent Runtime 做工具编排,用独立控制面做治理。
本文按真实落地顺序写:业务目标 → 分层架构 → Agent 与 Prompt → RAG / 混合检索 → 控制面产品化 → 部署与权限 → 经验与演进。文中的项目 ID、桶名、Data Store 路径一律用占位符,不涉及真实账号与内部资源。
1. 业务背景与设计目标
企业里真正有价值的知识,往往散落在架构方案、SOP、Runbook、API 对接文档和工单复盘里。传统知识库有两个硬伤:
- 检索语义弱:无法理解「GKE 蓝绿升级失败后如何回滚」这类带上下文的工程问题,返回的是文件名而不是可执行步骤。
- 无法溯源:通用 LLM 会编造命令、参数和权限配置;出了事故无法证明「这句话来自哪份 Runbook」。
NextKB 因此被设计成 GCP 上的企业技术支持 Agent:员工既可以走独立 Web 门户,也可以在 Gemini Enterprise 里用 @NextKB 提问,两边打到同一套 Agent Runtime。
核心设计目标
- 高召回、零编造:事实来源是 GCS 非结构化文档 + Vertex AI Search(Discovery Engine)。系统指令强制「检索优先、禁止臆造」。
- 双通道接入:产品 SPA 走 FastAPI;Gemini Enterprise 直连 Reasoning Engine,不经过产品服务。
- 控制面 / 推理面解耦:会话、租户、ACL、用量落在控制面数据库;推理、Function Calling、RAG 落在 ADK Runtime。
- 企业级隔离:
tenant_id、文档 ACL、IAM 最小权限、防跨桶访问、审计日志。
一个容易被忽略但必须写进架构原则的点:控制面数据库不是知识库。SQLite / PostgreSQL 只存租户、连接器登记、会话审计、文档元数据与 chunk 自检索引。生产问答的事实层始终是 GCS + Vertex AI Search。
2. 总体系统架构
NextKB 当前仓库是 NextKB Core 的 Google Cloud Edition。Core 本身用 Provider Adapter 把 LLM、Embedding、Vector Store、Rerank、OCR、Storage、Agent Runtime、Connector 做成可替换合同,避免把产品焊死在一家云上。Google Cloud Edition 的默认绑定如下:
| Provider 合同 | Google Cloud Edition 默认 |
|---|---|
| LLM | Gemini on Vertex AI |
| Embedding | Vertex AI Embedding |
| Vector Store | Vertex AI Vector Search |
| Sparse Search | 本地 BM25 基线 |
| Rerank | Vertex AI Ranking API |
| OCR | Document AI |
| Storage | GCS |
| Agent Runtime | ADK / Gemini Enterprise Agent |
产品分层可以画成:
flowchart TB
subgraph ClientLayer["1. 接入层"]
WebUI["企业 Web 门户\n静态 SPA"]
AdminUI["治理控制台\n/admin"]
GE["Gemini Enterprise\n@NextKB"]
end
subgraph ControlPlane["2. 控制面 Cloud Run / FastAPI"]
Router["网关\n/api/chat /api/conversations"]
AuthModule["鉴权与 RBAC\nAccess Code / IAP / OIDC / SAML"]
AuditDB[("控制面 DB\nSQLite 或 Cloud SQL")]
DocSync["连接器与知识同步"]
Hybrid["Hybrid Retrieval\nBM25 + Vector + RRF"]
end
subgraph AgentRuntime["3. 推理面 Vertex AI Agent Runtime"]
ADKRunner["Google ADK Runner"]
SystemPrompt["结构化系统指令"]
SearchTool["VertexAiSearchTool"]
end
subgraph DataLayer["4. 数据与检索层"]
GCS["Cloud Storage 文档桶"]
Datastore["Vertex AI Search Data Store"]
VectorIdx["Vector Search Index"]
end
WebUI --> Router
AdminUI --> Router
GE --> ADKRunner
Router --> AuthModule
Router --> AuditDB
Router --> DocSync
Router -->|"AgentClient 流式代理"| ADKRunner
DocSync --> GCS
DocSync --> Datastore
ADKRunner --> SystemPrompt
ADKRunner --> SearchTool
SearchTool --> Datastore
Datastore --> GCS
Hybrid --> VectorIdx
Hybrid --> AuditDB为什么这样拆
FastAPI 控制面只做它擅长的事:静态 UI、会话持久化、多租户、RBAC、连接器、审计与计量。
Reasoning Engine只做推理编排:选模型、调 VertexAiSearchTool、把 Grounding Metadata 吐回流式通道。
运行形态对照:
| 形态 | 入口 | Agent 后端 | 说明 |
|---|---|---|---|
| 本地开发 | 127.0.0.1:8000 + /admin | AGENT_BACKEND=adk | 同时起 adk web 与 uvicorn |
| Gemini Enterprise | @NextKB | Reasoning Engine | GE 直连 Runtime,不经过 FastAPI |
| Cloud Run 生产 | 产品 URL + /admin | 推荐 reasoning_engine | 容器更轻,复用已部署 Agent |
ADK 有一个硬约束:同一个 Agent 里 VertexAiSearchTool 不能和其他 tool 共存。MVP 因此保持单工具。以后要接工单系统、变更窗口查询等外部动作,正确做法是协调 Agent + sub-agent + AgentTool,而不是往 root_agent.tools 里硬塞第二个函数。
3. 基于 Google ADK 的 Agent 开发
3.1 智能体定义与模型选型
Agent 入口在 nextkb/agent.py。生产主模型走环境变量,并预留 fallback,避免单模型配额打满后整条问答链路宕掉。
# nextkb/agent.py(示意,已脱敏)
from google.adk.agents import Agent
from google.adk.tools.vertexai_search_tool import VertexAiSearchTool
import os
search_tool = VertexAiSearchTool(
data_store_id=os.environ["VERTEXAI_DATASTORE_ID"],
)
SYSTEM_INSTRUCTION = """
你是 NextKB,企业技术支持与解决方案专家。
只基于检索到的企业知识库作答,不得臆造文档、命令或权限配置。
回答规范:
1. 结论先行:1-2 句给出可行性或核心结论。
2. 结构化步骤:用编号拆解操作。
3. 生产级示例:代码或 CLI 标明必要参数与鉴权方式。
4. 避坑:指出 IAM、配额、多租户隔离等高频陷阱。
5. 溯源:引用检索到的文档名称或 URI,禁止伪造来源。
"""
root_agent = Agent(
name="nextkb_agent",
model=os.environ.get("AGENT_MODEL_PRIMARY", "gemini-flash-latest"),
description="NextKB 企业技术支持与知识问答智能体",
instruction=SYSTEM_INSTRUCTION,
tools=[search_tool],
)VERTEXAI_DATASTORE_ID 必须在 import 阶段存在,否则 Agent 进程直接失败——这是有意为之:没有 Data Store 的 Agent 会上线成「会聊天的幻觉机」。
完整资源路径形态如下(把项目与 Data Store 名换成你自己的):
projects/${GCP_PROJECT_ID}/locations/global/collections/default_collection/dataStores/${DATASTORE_ID}3.2 Prompt 与 Grounding
工业级 RAG 不是「把检索结果塞进 context 就结束」。NextKB 用两层约束:
- 输出范式:结论 → 编号步骤 → 代码/命令 → 注意事项 → 引用。
- Grounding 提取:从 Vertex AI Search 返回的
GroundingChunks/GroundingAttributions解析文档名与 GCS URI,前端渲染成溯源徽章。
产品聊天默认仍走 Agent 原生检索(NEXTKB_CHAT_CONTEXT_MODE=agent_native)。只有打开 hybrid_prepend 时,控制面才会把 Hybrid Retrieval 组装好的带编号上下文拼进请求。这避免了「控制面 RAG」和「工具 RAG」两套上下文互相打架。
4. 知识库流水线:从文档到可检索 chunk
4.1 事实层怎么建
Vertex AI Search Data Store 创建时必须 contentConfig: CONTENT_REQUIRED。数据源选 Cloud Storage、非结构化文档。推荐:
| 配置项 | 建议 |
|---|---|
| Location | global |
| Parser | Layout Parser(表格/版式更稳) |
| Include ancestor headings | 开启 |
| 上传 MIME | 同步时统一 text/plain。Vertex AI Search 不吃 text/markdown |
文档组织建议按领域分前缀,而不是把所有文件丢进桶根目录:
gs://your-knowledge-bucket/
architecture/
runbooks/
sop/
faq/
onboarding/POC 用 10–30 份高质量 Runbook / SOP 就够;零散笔记召回噪声极大。
4.2 控制面解析与同步
后台上传链路:
- 文本 / Markdown 本地 UTF-8 解析。
- PDF / 图片走 Document AI Processor(
DOCUMENTAI_PROCESSOR_NAME)。 - 解析文本写入
document_chunks,供 ACL 自检与本地检索回归。 - 点击同步:以
text/plain上传到KNOWLEDGE_BUCKET,再触发 Discovery Enginedocuments:import。
未配置 GCP 凭据时,后台必须返回明确原因,而不是让半条链路静默失败。Cloud Run 文件系统是临时盘,不要把生产知识正文只放在容器本地。
4.3 Connector 与增量
连接器登记在 connectors / connector_runs / connector_states。敏感字段(token、password、key)展示时脱敏。
| Worker | 行为要点 |
|---|---|
gcs | 按 bucket/prefix 拉取支持格式,用 source_uri 幂等 upsert |
google_drive | 导出 Docs/Sheets/Slides,映射 user/group/domain ACL;use_change_tokens=true 时走 Changes API 增量并删除已移除文件 |
| SharePoint / Confluence / Slack / GitHub / Jira | 基础 API 同步、分页、重试、inline documents |
同步文档携带 source_connector_id、source_uri、content_hash、source_updated_at,避免反复同步复制出一堆重复文档。
5. 检索层:ACL、混合融合与 RAG 组装
企业 RAG 的真正难点不是 embedding 模型,而是 权限感知检索。NextKB 文档可见性为 tenant / restricted / public,细粒度名单在 document_acls。
Vector Search datapoint 带 restricts,查询时按当前 principal 生成允许列表,示意:
tenant_id: ["default"]
acl: ["tenant:default", "group:platform", "user:user@example.com", "public"]Hybrid Retrieval 流水线:
- Sparse:本地 BM25-like 检索,先做 ACL prefilter。
- Vector:Vertex AI Vector Search
find_neighbors。 - Fusion:Reciprocal Rank Fusion 合并同一 chunk 的多路得分。
- Rerank:Discovery Engine Ranking API
default_ranking_config:rank。 - Fallback:Vector 或 Ranking 不可用时退回 fused / local 结果。
rag_context 再按字符预算压缩候选,生成 [1]、[2] 引用编号,后台可用 /admin/api/enterprise/rag/preview 做无模型预览。检索质量用 golden set(retrieval_eval_cases / retrieval_eval_runs)闭环,而不是靠「感觉召回还行」。
6. 控制面与产品体验
6.1 零构建静态前端
产品 UI 与 /admin 都由同一个 FastAPI 进程托管,无 Node 打包。好处是 Cloud Run 镜像简单、发布路径短。聊天走 SSE:
- 思考中 → 检测到 function_call 显示「正在检索知识库…」
- 累积
content.parts[].text做 Markdown 打字机 - 结束时挂上 grounding 引用;失败则中文错误 + 落库
6.2 会话持久化
sequenceDiagram
participant User as 浏览器
participant API as FastAPI
participant RE as Agent Runtime
participant DB as 控制面 DB
User->>API: POST /api/session
API->>RE: 创建 Agent session
RE-->>API: session_id
User->>API: POST /api/chat
API->>DB: 用户消息 + 会话标题
API->>RE: 流式推理
loop SSE
RE-->>API: text / function_call / citations
API-->>User: data: { text, model_version }
end
API->>DB: 助手全文 + Grounding客户端用 localStorage 记住活跃 sessionId;服务端 conversations / messages 双表落库。后端不可用时 /api/session 仍返回本地 sessionId 和 backendReady=false,前端能展示可读警告,而不是白屏。
6.3 身份与治理
| 模式 | 用途 |
|---|---|
access_code | 本地 / 演示 |
google_iap | Cloud Run + IAP 头;可验 X-Goog-Iap-Jwt-Assertion |
trusted_headers | 企业网关注入 |
oidc / saml | IdP 认证后注入 claim headers |
解析后的 principal(tenant_id、user_id、groups)进入会话审计、ACL 检索和 tenant_memberships。后台 RBAC:auditor 只读,admin 可写,owner 最高。SCIM /scim/v2 覆盖 Users / Groups / Bulk 基础操作。用量走 usage_events / tenant_quotas,可导出成本 CSV。
密码类凭据用加盐哈希存储;响应头加上 X-Frame-Options: DENY、X-Content-Type-Options: nosniff、Referrer-Policy 等。连接器配置里的密钥只存控制面,接口回显必须脱敏。
7. 云原生部署与安全边界
7.1 双流水线
Web 与 Gemini Enterprise 共用 Agent,因此发布顺序必须固定:先 Runtime,再把新 Engine ID 写进 Cloud Run 环境变量。
flowchart LR
Code["提交 nextkb/ 与 server/"] --> Tests["自动化测试"]
Tests --> Agent["adk deploy agent_engine"]
Agent --> SyncID["回写 REASONING_ENGINE_ID"]
SyncID --> Run["gcloud run deploy"]
Run --> Verify["Web 与 GE 端到端验证"]# 1) 部署 Agent Runtime(占位符)
adk deploy agent_engine \
--project="${GCP_PROJECT_ID}" \
--region="${GCP_AGENT_ENGINE_REGION}" \
--display_name="NextKB Agent" \
nextkb
# 2) 部署控制面
gcloud run deploy nextkb-ui \
--project="${GCP_PROJECT_ID}" \
--region="${CLOUD_RUN_REGION}" \
--source=. \
--set-env-vars="AGENT_BACKEND=reasoning_engine,REASONING_ENGINE_ID=${NEW_ID}"生产控制面用 NEXTKB_DB_URL 指向 Cloud SQL PostgreSQL,不要把 SQLite 文件放在可丢失的容器盘上。
7.2 权限最小化
- Reasoning Engine 服务账号:检索侧
roles/discoveryengine.viewer一类只读角色即可。 - Cloud Run 服务账号:
roles/aiplatform.user用于调用 Runtime。 - 后台同步 GCS 时强制校验 bucket 命名空间与前缀,禁止扫到租户未授权的桶。
- IAP 模式建议设置 JWT audience,并开启 signed JWT 校验作为入口基线。
不要把真实项目号、服务账号 JSON、Data Store 全路径、内部邮箱写进文档或截图。示例一律用 ${GCP_PROJECT_ID}、gs://your-knowledge-bucket、user@example.com。
8. 经验总结与后续规划
已经验证过的收益
- 答疑成本下降:复杂拓扑、IAM 模板、API 样例可以按 Runbook 召回,而不是靠人口口相传。
- 一次索引,多端生效:同一 Data Store 同时服务 Web、移动端适配页和 Gemini Enterprise。
- Serverless 成本结构:无流量时 Cloud Run 可缩到接近零;推理面按调用计费。
落地时踩过的坑
- Markdown 原文件直接导入 Search 会因 MIME 被拒或解析质量差,同步层必须转
text/plain。 - 单 Agent 多 tool 与
VertexAiSearchTool冲突,外部动作要拆 sub-agent。 - 控制面 RAG prepend 和 Agent 原生 Search 同时开,容易出现引用编号对不上文档。
- Connector「能同步」不等于 SLA:限流、增量游标、ACL 映射必须用真实租户验收。
Roadmap
- Hybrid Fusion 作为默认生产检索,而不是仅后台自检。
- 连接器增量同步与供应商 ACL 精准对齐。
- 完整 SSO / SCIM 生命周期,而不是只信任网关头。
- 评测集与线上 Trace 打通,把幻觉率做成可回归指标。
FAQ
NextKB 的事实知识存在哪?
生产问答看 GCS + Vertex AI Search。控制面数据库只存元数据、审计、ACL 和本地 chunk 自检索引。
Web 门户和 Gemini Enterprise 是两套 Agent 吗?
不是。推荐共用同一个 Reasoning Engine。FastAPI 只代理产品入口;GE 直连 Runtime。
本地怎么开发?
AGENT_BACKEND=adk,本地起 ADK Web 与 FastAPI。不要在开发机写入真实生产 Data Store 的写权限。
如何证明回答不是编的?
检查 SSE / 落库消息里的 grounding 引用是否指向真实文档 URI;后台用 retrieval golden set 回归召回与权限过滤。
结语
NextKB 证明了一件事:企业知识库 Agent 的竞争力不在「再包一层聊天框」,而在 检索与推理托管、控制面治理、权限在检索前生效、发布流水线把双入口当成同一产品。Google ADK + Vertex AI Search + Cloud Run 能把这条链路从 POC 推到可审计的生产形态;真正耗时间的是文档质量、ACL 和评测,而不是再换一个模型名。
若你要从零复制,建议严格按这个顺序:先建 Data Store 与 20 份高质量文档 → 再挂 VertexAiSearchTool → 再补控制面会话与审计 → 最后才上连接器和混合检索。顺序反了,后面每一层都会在错误的事实上做功。
