Knowledge Starter
受众:开发者 摘要:项目知识扫描 + Markdown heading-aware 切片 + 关键词 / 本地向量 / hybrid 检索 + Ask 上下文返回。默认不依赖向量数据库或外部模型。
何时使用
| 场景 | 建议 |
|---|---|
| 搜索团队知识、公开业务内容和受控知识源 | Knowledge.search(...) |
| 给 AI Bot / 客服 / 文档助手提供检索上下文 | Knowledge.ask(...) 返回 snippet + citations |
| AI Task Handler 找资料 | Knowledge.search → Pipeline 组 prompt → 模型 Provider |
| 需要轻量向量检索 / 语义相似 | 使用默认 memory 向量库和 mode=vector / mode=hybrid |
| 需要 PDF / Word / Excel / OCR | 先由 Document starter 抽取文本,再进入 Knowledge 检索 |
| 需要后台查看知识源、文档、切片和索引状态 | 使用 Core Knowledge Admin contract |
| 需要后台轻量问一问 | 使用 Core Knowledge POST /api/v1/admin/knowledge/ask |
| 需要运维侧快速判断索引规模 | Knowledge.summary(source) 返回文档数、切片数、token 预算和向量配置状态 |
| 需要对外开放给第三方 | 不在第一阶段范围 |
Knowledge starter 只读取现有知识并生成可检索上下文,不生成 AI 回答。Core Knowledge Admin 可以在后台组合 AI Model 生成回答,但模型能力是可选增强;Admin 问一问默认不生成,且 chat.policy.generation-enabled=false 时即使请求 generate=true 也会回退检索摘要。应用默认 AI Model Provider 是 simulated,不会访问真实模型服务;真实 Provider 需要显式开启生成策略和 Provider 白名单。未配置可用模型、模型调用失败或流式链路不可用时,接口应回退到检索摘要和引用。默认 embedding 是本地 hashing 实现,不需要密钥。
快速开始
spring:
open:
knowledge:
enabled: trueList<KnowledgeSearchResult> results = Knowledge.search(
KnowledgeSearchRequest.builder()
.query("Web3 支付结算")
.mode(KnowledgeConstants.MODE_HYBRID)
.topK(5)
.includeContent(true)
.build()
);默认只扫描项目 .knowledge/ 团队知识目录,开发文档 docs/、Agent 记忆 .ai/ 和 AGENTS.md 不进入默认知识库;确需内部 Agent 检索时应另建受控来源显式配置。
Core Knowledge Admin Contract
spring-open-core-knowledge 已接入 Knowledge starter,并在 spring.open.knowledge.enabled=true 时暴露后台管理接口:
| 方法 | 路径 | 说明 |
|---|---|---|
GET | /api/v1/admin/knowledge/sources | 查询已配置知识来源 |
GET | /api/v1/admin/knowledge/documents?source=project | 查询来源扫描到的文档 |
GET | /api/v1/admin/knowledge/chunks?source=project | 查询来源切片 |
GET | /api/v1/admin/knowledge/search?query=配置&mode=hybrid&topK=8 | 搜索知识库 |
GET | /api/v1/admin/knowledge/chat/config | 查询 Knowledge Chat 生成策略、模型可用性和护栏配置 |
POST | /api/v1/admin/knowledge/agent-context | 查询后台身份可见的受控 Agent 上下文;不调用模型、不写会话 |
POST | /api/v1/admin/knowledge/ask | 基于检索上下文问答;可选调用 AI Model 生成回答 |
POST | /api/v1/admin/knowledge/ask/stream | 基于检索上下文流式问答;模型或流式链路不可用时返回降级事件 |
POST | /api/v1/knowledge/me/agent-context | 查询当前用户可见的受控 Agent 上下文;服务端覆盖用户身份 |
POST | /api/v1/knowledge/me/ask | 当前登录用户知识问答;用户端入口使用当前身份并可保存会话 |
POST | /api/v1/knowledge/me/ask/stream | 当前登录用户知识流式问答;流式不可用时前端回退普通问答 |
POST | /api/v1/admin/knowledge/refresh | 刷新指定来源内存索引;未传 source 时使用默认来源,传 all=true 时刷新全部启用来源 |
POST | /api/v1/admin/knowledge/sources/url/preflight | 预检受控文档站 URL 来源配置;只校验根 URL 和抓取边界,不保存配置、不刷新索引 |
后台页面位于 views/admin/src/views/knowledge/index.vue,读接口需要 knowledge:view,刷新索引、URL 来源预检和反馈类接口需要 knowledge:update。页面已提供来源、文档、切片、搜索结果、Knowledge Chat 配置状态和“问一问”入口;来源页签展示来源类型、标题、说明、启用状态、搜索 / 刷新能力、根路径和扫描范围,停用来源会禁用搜索和刷新动作。只有生成策略允许且开启“生成回答 + 流式”时才会调用 SSE 流式接口并增量渲染,支持取消当前流式请求,流式请求不可用时自动切换普通 /ask 完整回答。问答默认不保存会话历史;请求显式传 recordConversation=true 时,会在 Conversation 底座中记录用户问题和助手回答,Conversation 不可用或记录失败时只返回 warning,不影响 Knowledge 回答。
普通用户入口使用 /api/v1/knowledge/me/**,只要求当前用户已登录,不要求配置项权限。Controller 会覆盖请求中的 userId 为当前登录用户,防止前端伪造身份;App / PC 默认传 recordConversation=true、稳定 conversationKey 和一次性 clientMessageId,用于把知识问答沉淀到 Conversation 会话历史。Admin /api/v1/admin/knowledge/ask 仍保留后台运维语义,只在请求未带 userId 时填充当前后台用户,便于管理员排查知识库和模型策略。
PC 端知识助手默认使用 business.public 来源。该来源由 Core Knowledge 聚合公开业务 contributor,不直接依赖业务模块实现,当前包含 mall.public-products(已发布商品)、cms.published-content(已发布 CMS 内容)、blog.published-articles(已发布文章)和 forum.public-topics(可见社区主题)。PC 页面同时提供来源筛选,可单独查询商品、CMS、文章、社区或团队知识;业务内容刷新仍按各自真实 source 或 business.public 聚合 source 进入 KnowledgeIndexer。
/agent-context 是给 Agent、插件或业务编排层使用的受控上下文接口。它复用 /ask 的请求体,但服务端会强制 generate=false、returnContext=true,只返回当前身份可见的 contexts 和 citations,不调用模型、不写 Conversation、不记录 Knowledge Chat 审计。Admin 入口按 knowledge:view 权限和后台身份过滤,用户入口按当前登录用户过滤;请求体里的 userId / tenantId / adminAccess 不会绕过服务端可见性判定。
刷新是 source 级通用入口,适用于文件系统、业务贡献方、受控文档站等所有已配置来源。未传 source 时只刷新 default-source,不代表刷新全部来源;需要批量重建时必须显式传 all=true,服务端只遍历已启用且可刷新的来源,并返回聚合统计和每个来源的子结果,避免误触停用来源。业务来源还支持事件触发刷新:CMS / Blog / Forum / Mall 在公共内容创建、更新、发布状态变化或删除后发布 Runtime 中立事件,Core Knowledge 在事务提交后按来源编码调用 KnowledgeIndexer.refresh(source)。业务模块不直接调用 Knowledge indexer,Knowledge 也不依赖业务模块实现。
type=url / web-docs 来源在通用刷新基础上额外支持 HTTP 增量能力:加载器会复用上一轮文档的 ETag / Last-Modified 发起条件请求,远端返回 304 时复用缓存正文并标记 refreshStatus=unchanged;远端返回新内容时根据 contentHash 标记 created 或 updated;远端短时不可用、非 2xx 或页面超过大小限制时,如果本地已有缓存,会继续返回旧文档并标记 refreshStatus=stale,避免一次网络波动清空知识库。
刷新结果 KnowledgeRefreshResultVO 会返回 source、sourceCount、sources、documentCount、chunkCount、createdDocumentCount、updatedDocumentCount、unchangedDocumentCount、staleDocumentCount、startedAt、finishedAt 和 durationMillis;单来源刷新时 sourceCount=1 且 sources 为空,all=true 批量刷新时 source=all 且 sources 包含每个来源的子结果。Admin 页面会在刷新后展示新增、更新、未变化、旧缓存、来源数量和耗时统计。文档列表 KnowledgeDocumentVO 会带出 refreshStatus 和原始 metadata,Admin 文档页签展示刷新状态和关键 metadata;URL 来源 metadata 包含 canonicalUrl、rootUrl、httpStatus、contentType、etag、lastModified、contentHash、fetchedAt 等字段,方便后台和运维侧判断知识是否新增、未变化、已更新或正在使用旧缓存兜底。
Admin 页面提供“URL 预检”抽屉,可从当前 url / web-docs 来源带入已有 root 和路径范围,也可以手动录入一个新文档站。预检接口只对 root URL 发起一次 HTTP GET,并按同源、允许路径、重定向、HTTP 2xx、content-type、页面大小和 sitemap 同源规则返回校验结果;它不会保存配置,也不会触发抓取或刷新。预检通过后,抽屉会生成一段可复制到配置文件的 spring.open.knowledge.sources.<name>.url.* YAML 片段。
POST /api/v1/admin/knowledge/sources/url/preflight 请求体:
{
"source": "docs-site",
"rootUrl": "https://example.com/docs",
"sitemapUrl": "https://example.com/docs/sitemap.xml",
"allowedPathPrefixes": ["/docs"],
"maxDepth": 1,
"maxPages": 30,
"maxBytesPerPage": 1048576,
"maxRedirects": 3,
"connectTimeoutMillis": 5000,
"requestTimeoutMillis": 10000,
"allowedContentTypes": [
"text/html",
"application/xhtml+xml",
"text/markdown",
"text/plain"
],
"userAgent": "KnowledgeBot"
}响应中的 valid 表示该配置是否可作为受控文档站来源使用;reachable、contentTypeAllowed、sizeAllowed 用于拆分原因;errors 和 warnings 返回稳定短码,前端会转换为中文提示。常见短码包括 root_url_required、scheme_not_supported、redirect_origin_not_allowed、redirect_path_not_allowed、http_status_not_success、content_type_not_allowed 和 content_too_large。
三端可嵌入组件:
| 端 | 组件 / API | 传输策略 |
|---|---|---|
| Admin | views/admin/src/views/knowledge/components/KnowledgeChatPanel.vue / views/admin/src/api/knowledge.ts | 浏览器端优先 /ask/stream,失败自动回 /ask |
| App | views/app/src/pages/knowledge/index.vue + views/app/src/components/KnowledgeChatPanel.vue / views/app/src/api/knowledge.js | 默认普通 /me/ask,适配非 SSE 客户端环境 |
| PC | views/pc/app/pages/knowledge.vue + views/pc/app/components/KnowledgeChatPanel.vue / views/pc/app/features/shared/useKnowledgeChatApi.ts | 浏览器端优先 /me/ask/stream,失败自动回 /me/ask |
三端组件会把服务端 warnings 短码转换成普通用户能理解的提示,不直接向用户展示 ai_model_failed 这类内部短码。PC 端只有用户开启“实时显示回答”时才尝试流式请求;客户端不支持流式响应或流式请求失败时,会提示已切换普通回答并继续展示 /ask 完整结果。
POST /api/v1/admin/knowledge/ask、POST /api/v1/knowledge/me/ask、以及对应 /ask/stream 请求体:
{
"source": "project",
"question": "Knowledge 如何接入 AI Model?",
"topK": 6,
"returnContext": true,
"generate": true,
"provider": "simulated",
"model": "simulated-default",
"temperature": 0.2,
"maxTokens": 512,
"recordConversation": true,
"conversationKey": "admin-knowledge",
"clientMessageId": "ask-20260607-0001"
}字段说明:
| 字段 | 说明 |
|---|---|
source | 知识来源编码,未传时使用 spring.open.knowledge.default-source |
question | 用户问题,必填 |
topK | 检索上下文数量,范围 1..20 |
returnContext | 是否在响应中返回上下文列表;生成 prompt 内部仍会使用上下文 |
generate | 是否调用 AI Model 生成回答,默认 false |
provider / model | 可选模型路由覆盖;不传时由 AI Model starter 默认路由决定 |
temperature / maxTokens | 可选模型参数 |
recordConversation | 是否把本次问答写入 Conversation,Admin 默认 false,App / PC 用户入口默认 true |
conversationId | 可选已有会话 ID;未传时可通过 conversationKey 复用或创建 Knowledge 会话 |
conversationKey | 可选会话键,服务端会按 knowledge:{userId}:{conversationKey} 归一成 Conversation key |
clientMessageId | 可选幂等消息 ID;助手回答会派生 {clientMessageId}:assistant |
recordConversation=true 时,/me/** Controller 始终使用当前登录用户作为 userId;Admin /api/v1/admin/knowledge/ask 在请求未带 userId 时填充当前后台用户;Service 也保留 userId 字段,便于开放 API 或应用装配层在受控上下文中显式传入。会话消息使用 contentType=text,并在 attributes 中写入 source=knowledge、role=user|assistant、knowledgeSource、answerMode、generated、Provider / model 等轻量元数据。Knowledge 不复制 Conversation 私有状态,也不引入独立消息表。
响应中的 answerMode 用于前端和审计区分回答来源:
answerMode | 说明 |
|---|---|
generated | 已调用 AI Model 并返回生成式回答 |
extractive | 未调用模型,或模型不可用 / 失败后回退到检索摘要 |
no-context | 没有检索到可用于回答的上下文 |
响应还会在记录成功时返回 conversationRecorded=true、conversationId、userMessageId 和 assistantMessageId,前端可据此跳转或继续追加上下文。
warnings 当前可能包含 no_context、ai_generation_disabled、ai_source_not_allowed、ai_provider_not_allowed、ai_model_not_allowed、ai_no_context_generation_disabled、ai_model_unavailable、ai_model_failed、conversation_user_required、conversation_unavailable、conversation_failed、ai_guard_request_limited、ai_guard_token_budget_exceeded、ai_guard_concurrency_limited、ai_guard_prompt_too_large、ai_guard_max_tokens_clamped、ai_guard_duplicate_merged。这些 warning 不表示接口失败,只表示回答、模型调用或会话记录已降级;前端应继续展示检索摘要、引用和可用回答。
POST /api/v1/admin/knowledge/ask/stream 使用 text/event-stream,请求体与 /ask 一致。事件结构:
| 事件 | 说明 |
|---|---|
meta | 首个事件,携带问题、来源、contexts、citations、maxScore 等元数据 |
delta | 模型增量文本,前端按顺序拼接到回答区 |
done | 生成完成,携带最终 answer、Provider / model、finishReason、usage |
result | 非流式完整结果,常用于未启用生成、无模型、模型 stream 失败或服务端降级 |
流式模型不可用、连接失败、客户端不支持 SSE 或中途断开时,前端必须保留普通 /ask 完整回答或任务状态查询作为兜底,不能把 SSE 作为唯一可用入口。当前 Admin / PC 页面已经实现流式失败后自动回退 /ask,App 端默认使用普通 /me/ask。
Facade API
// 关键词 / 向量 / hybrid 搜索
List<KnowledgeSearchResult> results = Knowledge.search(
KnowledgeSearchRequest.builder()
.query("...")
.mode("hybrid") // keyword / vector / hybrid
.topK(8)
.includeContent(false) // 默认只返回 snippet
.source("project") // 限定知识源
.build()
);
// 问答上下文(返回 snippet + citations,不生成回答)
KnowledgeAskResult result = Knowledge.ask(
KnowledgeAskRequest.builder()
.question("为什么配置前缀使用 spring.open.*?")
.topK(6)
.returnContext(true)
.build()
);
// 来源索引摘要(不触发 AI 回答或外部模型调用)
KnowledgeIndexSummary summary = Knowledge.summary("project");返回字段
| 字段 | 说明 |
|---|---|
documentKey | 文档 key |
chunkIndex | 切片序号 |
title | 标题 |
path | 文件路径 |
headingPath | 标题路径,例 Web3 > 支付结算 > 风险审计 |
score | 相关性分数 |
snippet | 摘要片段 |
content | 完整内容(仅 includeContent=true) |
源码机制骨架
| 类型 | 机制职责 |
|---|---|
Knowledge | 静态 Facade,提供业务侧短名入口 |
KnowledgeManagerProvider | 将 Facade 绑定到 Spring 容器内的 KnowledgeManager |
KnowledgeManager | 管理文档加载、切片、关键词检索和 Ask 上下文组装 |
DefaultKnowledgeManager | 默认实现,每次按需加载来源、切片并执行轻量关键词检索 |
KnowledgeIndexSummary | 来源级索引摘要,包含文档数、切片数、token 总量、平均切片 token、索引开关和默认向量存储 |
KnowledgeDocumentLoader | 文档加载 SPI,当前默认实现读取本地文件系统知识源 |
CompositeKnowledgeDocumentLoader | 聚合多个加载器,按来源编码分派到文件系统来源或业务来源 |
FilesystemKnowledgeDocumentLoader | 按配置 paths / excludes / extensions 读取本地文件源文档;metadata 固定包含 source、size、lastModifiedAt,容器内存在 DocumentManager 时优先消费 Document starter 的抽取结果 |
UrlKnowledgeDocumentLoader | 读取 type=url / web-docs 受控文档站来源;限制同源、允许路径、深度、页数、字节数、content-type 和重定向,并用 ETag / Last-Modified / contentHash 维护刷新状态 |
KnowledgeSourceContributor | 业务模块知识来源贡献 SPI,由 Blog / CMS / Forum / Mall 等业务模块注册 Bean 输出中性文档快照 |
KnowledgeSourceDocument | 业务知识文档快照,包含来源、业务类型 / ID、标题、摘要、正文、URL、可见性、租户 / 用户、更新时间、内容 hash 和轻量 metadata |
KnowledgeSourceDocumentLoader | 将启用的业务贡献方快照转换为 KnowledgeDocument,供统一切片、索引和检索 |
KnowledgeSourceChangedEvent | Knowledge starter 中立事件,业务公共内容变更后发布,Core Knowledge listener 在事务提交后按 source 刷新索引 |
KnowledgeChunker | 文档切片 SPI |
MarkdownHeadingKnowledgeChunker | 按 Markdown 标题优先切片,尽量保留标题路径和代码块 |
KnowledgeEmbeddingProvider | 文本向量化 SPI,默认本地 hashing embedding |
KnowledgeVectorStore | 向量存储和相似度检索 SPI,默认内存实现 |
KnowledgeIndexer | 文档扫描、切片和向量索引的内部编排点 |
KnowledgeSearchRequest / KnowledgeSearchResult | 搜索请求和结果 contract |
KnowledgeAskRequest / KnowledgeAskResult | Ask 上下文请求和结果 contract |
扩展边界
Knowledge starter 默认提供本地 hashing embedding 和内存向量库;生产级 RAG 扩展点仍保持在 Knowledge 边界内:
- 业务模块接入公共知识来源时实现
KnowledgeSourceContributor,输出KnowledgeSourceDocument快照;Knowledge 不直接依赖 Blog / CMS / Forum / Mall 等业务模块。 - 自定义非业务知识来源时实现
KnowledgeDocumentLoader,例如数据库、远程 API 或其他文件系统。 - 自定义切片规则时实现
KnowledgeChunker,例如按段落、固定窗口或业务字段切片。 - 配置
embedding.provider=ai-model复用 AI Model starter 的 embeddings;需要更特殊协议时实现KnowledgeEmbeddingProvider。 - 自定义向量存储时实现
KnowledgeVectorStore,例如 pgvector、Qdrant 或 OpenSearch。 DefaultKnowledgeManager支持keyword/vector/hybrid三种检索模式;默认不触发外部模型或外部向量库。Knowledge.ask(...)只返回 contexts 和 citations,answer第一阶段保持空字符串;Core Knowledge Admin 的/ask组合接口可按请求调用 AI Model,失败时回退到检索摘要。- Core Knowledge Admin 的
/ask和/ask/stream可选写入 Conversation 会话历史;该能力只通过KnowledgeConversationRecorder桥接 Conversation Service,不改变 Knowledge starter 的纯检索边界。 - Core Knowledge Admin contract 只面向后台运维,不承担第三方开放接口职责。
- PDF、Office、OCR 等文档解析先通过 Document starter 抽取文本,再交给 Knowledge;Knowledge 文件系统加载器只消费
DocumentExtractResult,不直接依赖 Tika / PDFBox / POI。
业务模块知识来源
公共、已发布、适合问答的业务内容通过 KnowledgeSourceContributor 接入。业务模块只注册自己的 contributor Bean,Knowledge starter 通过 ObjectProvider<KnowledgeSourceContributor> 聚合启用来源,并把快照转为统一 KnowledgeDocument 后进入切片和索引链路。
当前已内置的业务贡献方:
| 来源编码 | 模块 | 内容边界 | 备注 |
|---|---|---|---|
cms.published-content | CMS | 已发布公共 CMS 内容 | 输出页面、公告、专题、内容块、导航等可公开展示内容 |
blog.published-articles | Blog | 已发布文章 | 免费文章输出正文;付费 / VIP 文章只输出公开预览或摘要,不索引锁定正文 |
forum.public-topics | Forum | 公开可见主题 | 输出公开板块下可见主题的标题、摘要、首帖正文、作者和互动热度 |
mall.public-products | Mall | 已上架公开商品 | 输出商品名称、摘要、详情、分类、价格和公开图片,不索引订单 / 购物车 / 支付 / 售后 / 结算数据 |
form.public-templates | Form | 公开模板 | 输出 active official 模板的说明、字段 JSON 和设置 JSON,不索引用户提交数据或协作权限 |
meeting.help-docs | Meeting | 会议帮助说明 | 输出会议能力、入会、主持人控制、资料 / 聊天 / 提醒、录制 / 转写 / 纪要和开放 API 的公开帮助快照,不索引会议实例、成员、录制文件、转写或纪要正文 |
@Component
class BlogPublishedArticleKnowledgeSourceContributor implements KnowledgeSourceContributor {
@Override
public String sourceCode() {
return "blog.published-articles";
}
@Override
public String title() {
return "Blog published articles";
}
@Override
public List<KnowledgeSourceDocument> documents() {
return publishedArticles().stream()
.map(article -> KnowledgeSourceDocument.builder()
.businessType("article")
.businessId(String.valueOf(article.id()))
.title(article.title())
.summary(article.summary())
.content(article.publicPreviewContent())
.url("/blog/articles/" + article.slug())
.visibility(KnowledgeConstants.VISIBILITY_PUBLIC)
.updatedAt(article.updatedAt())
.build())
.toList();
}
}业务来源快照只表达可索引文本和轻量引用信息,不暴露模块表结构、状态机或权限细节。私有资料、交易数据、会议纪要、用户提交数据和权限知识库需要先完成权限过滤后再接入。
配置项
spring:
open:
knowledge:
enabled: true
default-knowledge-base: project
default-source: project
default-top-k: 8
default-vector-store: memory
sources:
project:
enabled: true
root: .
paths:
- .knowledge
excludes:
- target/**
- public/**
- storage/**
- views/**/node_modules/**
- .ai/memory/**
- .ai/tasks/branch-plans/**
extensions:
- .md
- .markdown
- .txt
chunking:
max-tokens: 800
overlap-tokens: 100
respect-markdown-heading: true
preserve-code-block: true
index:
enabled: true
persistent-enabled: false
persistent-provider: pgvector
incremental-scan-enabled: true
keyword-weight: 1.0
vector-weight: 4.0
min-vector-score: 0.05
vector-stores:
memory:
enabled: true
provider: memory
pgvector:
enabled: false
provider: pgvector
options:
table: knowledge_embedding
vector-column: embedding_vector
metadata-column: metadata_json
embedding:
provider: hashing
external-enabled: false
fallback-to-hashing: true
external-provider:
external-model:
dimensions: 256
min-token-length: 1
chat:
policy:
generation-enabled: false
default-generate: false
default-provider: simulated
default-model:
default-temperature: 0.2
allowed-sources: []
allowed-providers:
- simulated
allowed-models: []
generate-without-context: false
no-context-answer: 未检索到可用于回答的知识上下文。
guard:
enabled: true
default-max-tokens: 512
max-tokens-per-request: 1024
max-prompt-tokens: 4096
requests-per-minute: 30
tokens-per-day: 100000
concurrent-requests: 4
rate-limit-store:| 配置 | 默认值 | 说明 |
|---|---|---|
enabled | true | 启用开关 |
default-knowledge-base | project | 默认知识库(写入 / 检索归属) |
default-source | project | 默认知识来源 |
default-top-k | 8 | 默认返回结果数 |
default-vector-store | memory | 默认向量存储配置名;内置 provider 包含 memory 和默认关闭的 pgvector |
sources.<name>.extensions | .md / .markdown / .txt | 扫描的文件扩展名;接入 Document starter provider 后可显式加入 .pdf / .docx 等富文档扩展名 |
sources.<name>.language | zh-CN | 来源默认语言 |
sources.<name>.type | filesystem | 来源类型;本地文件使用 filesystem,受控文档站使用 url / web-docs |
sources.<name>.root | . | 来源根目录 |
sources.<name>.paths | 项目知识路径 | 要扫描的文件或目录 |
sources.<name>.excludes | 内置排除规则 | 要排除的 glob |
sources.<name>.url.root-url | 空 | 文档站根 URL;仅 type=url / web-docs 生效 |
sources.<name>.url.sitemap-url | 空 | 可选 sitemap URL;只接受同源 sitemap,页面仍按 allowed path 过滤 |
sources.<name>.url.allowed-path-prefixes | root URL 路径 | 允许抓取的路径前缀,默认使用 root URL 的 path |
sources.<name>.url.max-depth | 1 | 最大递归深度;不执行 JS,不抓登录态页面 |
sources.<name>.url.max-pages | 30 | 单次最多抓取页数 |
sources.<name>.url.max-bytes-per-page | 1048576 | 单页最大字节数,超过后跳过 |
sources.<name>.url.allowed-content-types | HTML / Markdown / text | 允许处理的 content-type 前缀 |
sources.<name>.url.connect-timeout | 5s | HTTP 连接超时 |
sources.<name>.url.request-timeout | 10s | 单次请求超时 |
sources.<name>.url.max-redirects | 3 | 最多跟随重定向次数;目标仍必须同源且命中允许路径 |
sources.<name>.url.user-agent | KnowledgeBot | 抓取文档站时使用的 User-Agent |
chunking.max-tokens | 800 | 单切片最大近似 token |
chunking.overlap-tokens | 100 | 切片重叠近似 token |
chunking.respect-markdown-heading | true | 是否按 Markdown 标题分块 |
chunking.preserve-code-block | true | 是否尽量不拆代码块 |
index.enabled | true | 是否启用内存向量索引;关闭后 vector / hybrid 回退为关键词检索 |
index.persistent-enabled | false | 是否启用生产持久索引;默认关闭,避免本地刷新意外依赖外部向量库 |
index.persistent-provider | pgvector | 生产持久索引 provider 标识;当前内置 pgvector provider 仍需显式启用 |
index.incremental-scan-enabled | true | 是否暴露增量扫描状态;当前 URL / web-docs 来源通过 ETag / Last-Modified / contentHash 返回 created / updated / unchanged / stale |
index.keyword-weight | 1.0 | hybrid 模式关键词分数权重 |
index.vector-weight | 4.0 | hybrid 模式向量相似度权重 |
index.min-vector-score | 0.05 | 向量结果最小相似度 |
vector-stores.<name>.enabled | true / false | 是否启用该向量存储配置 |
vector-stores.<name>.provider | memory | 向量存储 provider;内置 memory / pgvector,其他向量库通过自定义 KnowledgeVectorStore bean 接入 |
vector-stores.<name>.options | {} | provider 专属扩展配置,例如 pgvector 表名、向量列名和 metadata 列名 |
embedding.provider | hashing | embedding provider;hashing 为本地默认,ai-model 通过 AI Model starter 调用 embeddings |
embedding.external-enabled | false | 是否启用外部 embedding;默认关闭,避免索引刷新触发外部模型成本 |
embedding.fallback-to-hashing | true | 外部 embedding 失败或 AI Model 不可用时是否回退到本地 hashing |
embedding.external-provider | 空 | 使用 ai-model provider 时的 AI Model Provider 覆盖 |
embedding.external-model | 空 | 使用 ai-model provider 时的 embedding 模型覆盖 |
embedding.dimensions | 256 | 默认 hashing embedding 维度 |
embedding.min-token-length | 1 | 默认索引 token 最小长度 |
chat.policy.generation-enabled | false | 是否允许 Knowledge Chat 调用模型生成;默认关闭,保证检索摘要和引用始终可用 |
chat.policy.default-generate | false | 请求未传 generate 时的默认值 |
chat.policy.default-provider | simulated | 请求未传 Provider 时使用的默认 Provider;真实 Provider 需显式配置 |
chat.policy.default-model | 空 | 请求未传模型时使用的默认模型 |
chat.policy.default-temperature | 0.2 | 请求未传 temperature 时使用的默认温度 |
chat.policy.allowed-sources | 空 | 允许生成的来源白名单;为空表示不限制来源 |
chat.policy.allowed-providers | simulated | 允许生成的 Provider 白名单;默认只允许模拟 Provider |
chat.policy.allowed-models | 空 | 允许生成的模型白名单;为空表示不限制模型 |
chat.policy.generate-without-context | false | 无检索上下文时是否仍允许调用模型;默认直接返回 no-context |
chat.policy.no-context-answer | 固定中文提示 | 无检索上下文时返回的回答 |
chat.guard.enabled | true | 是否启用 Knowledge Chat 模型调用护栏;只影响 generate=true 的模型生成,不影响检索摘要 |
chat.guard.default-max-tokens | 512 | 未传 maxTokens 时的默认生成 token 上限 |
chat.guard.max-tokens-per-request | 1024 | 单次生成 token 上限,超过时裁剪并返回 ai_guard_max_tokens_clamped |
chat.guard.max-prompt-tokens | 4096 | 单次 prompt 近似 token 上限,超过时不调用模型并回退检索摘要 |
chat.guard.requests-per-minute | 30 | 单个主体每分钟最多生成请求次数;非正数表示不限制 |
chat.guard.tokens-per-day | 100000 | 单个主体每天最多消耗近似 token;非正数表示不限制 |
chat.guard.concurrent-requests | 4 | 本实例同时进行的生成调用上限;非正数表示不限制 |
chat.guard.rate-limit-store | 空 | 可选 Rate Limit store 名称;为空时使用 Rate Limit starter 默认 store |
Knowledge Chat 先经过 chat.policy,再经过 chat.guard。策略层负责是否允许生成、来源白名单、Provider / model 白名单和无上下文策略;护栏层复用 Rate Limit starter 控制成本和并发。单机或本地学习默认使用 memory store;多实例生产环境建议把 Rate Limit 默认 store 切到 Redis / Redisson,才能让每分钟次数和每日近似 token 预算跨实例生效。策略拒绝、超出预算、并发满、prompt 过大或短时重复请求时,接口会回退到 extractive / no-context,保留 citations,不让模型不可用或 token 成本影响 Knowledge 基础检索能力。
生产 RAG 的默认姿态是“显式开启”:默认 memory 向量库和 hashing embedding 不访问外部服务;需要 PostgreSQL 持久向量索引时启用 pgvector store,并将 default-vector-store 指向 pgvector;需要真实 embedding 时设置 embedding.provider=ai-model、embedding.external-enabled=true,并通过 external-provider / external-model 指向已授权的 AI Model Provider。fallback-to-hashing=true 时外部模型短时失败会继续以本地 hashing 完成索引和检索;生产环境若希望配置错误直接暴露,可关闭 fallback。
扩展 SPI
不提供 Provider 切换。扩展能力通过 SPI:
- 实现
KnowledgeSourceContributor注册业务模块公共知识来源(Blog / CMS / Forum / Mall 等) - 配置
sources.<name>.type=web-docs接入受控文档站 URL 来源;内置 loader 只抓同源、允许路径前缀、限定页数 / 深度 / 字节数 / content-type 的公共文档,不执行页面脚本,并通过 ETag / Last-Modified / contentHash 支持增量刷新和 stale 缓存兜底 - 实现
KnowledgeDocumentLoader注册其他非业务自定义知识来源(数据库 / 远程 API / 其他文件系统) - 实现
KnowledgeChunker自定义切片器 - 实现
KnowledgeEmbeddingProvider接入外部 embedding 模型 - 使用内置
pgvectorstore,或实现KnowledgeVectorStore接入 Qdrant / OpenSearch / 专用向量库
向量检索演进
当前版本已提供本地 hashing embedding + 内置 memory 向量库,不需要外部模型、向量数据库或密钥,适合作为框架默认轻量能力;同时内置默认关闭的 PostgreSQL pgvector store,用于生产持久索引。进入生产级 RAG 阶段时建议保持三层边界:
| 层 | 作用 | 建议 |
|---|---|---|
KnowledgeEmbeddingProvider | 把文本切片转成向量 | 默认本地 hashing;通过可选 provider 接入 OpenAI-compatible、本地模型或自建服务 |
KnowledgeVectorStore | 保存向量并做相似度检索 | 内置 memory / pgvector;独立部署向量服务时优先 Qdrant |
KnowledgeManager | 对外提供 search / ask | 保持 facade 不变,内部组合关键词、向量和引用结果 |
Embedding Provider
Provider 面向「模型服务能力」,不是面向某个业务模块:
| Provider | 适用场景 | 默认依赖 |
|---|---|---|
disabled | 默认禁用向量生成,适合未配置模型服务或隔离诊断 | 无 |
openai-compatible | OpenAI / Azure OpenAI / 兼容 OpenAI 协议的模型网关 | 后续可选依赖 |
local | Ollama、自建模型服务或内网模型网关 | 后续可选依赖 |
建议配置形态:
spring:
open:
knowledge:
default-embedding-provider: disabled
embedding-providers:
openai-compatible:
provider: openai-compatible
enabled: false
base-url: ${SPRING_OPEN_KNOWLEDGE_EMBEDDING_BASE_URL:}
api-key: ${SPRING_OPEN_KNOWLEDGE_EMBEDDING_API_KEY:}
model: text-embedding-3-smallVector Store
向量存储只放在 Knowledge 边界内,不让业务模块直接依赖 pgvector / Qdrant / Milvus SDK:
| Store | 推荐级别 | 说明 |
|---|---|---|
pgvector | 第一优先 | 适合 PostgreSQL 项目,运维成本低,和文档元数据事务边界更容易收口 |
qdrant | 第二优先 | 独立向量服务,部署轻,适合中等规模语义检索 |
elasticsearch / opensearch | 按需 | 已有搜索集群时适合做关键词 + 向量混合检索 |
milvus | 后续 | 大规模向量检索再引入,第一阶段不建议默认依赖 |
memory | 内置默认 | 用于单测、预览或本地轻量验证,不作为生产级持久化方案 |
当前可绑定配置形态:
spring:
open:
knowledge:
default-vector-store: memory
vector-stores:
memory:
enabled: true
provider: memory
pgvector:
enabled: false
provider: pgvector
options:
table: knowledge_embedding
vector-column: embedding_vector
metadata-column: metadata_json
qdrant:
enabled: false
provider: qdrant
options:
url: ${SPRING_OPEN_KNOWLEDGE_QDRANT_URL:}
api-key: ${SPRING_OPEN_KNOWLEDGE_QDRANT_API_KEY:}pgvector store 只有在 default-vector-store 指向 provider 为 pgvector 的配置、classpath 含 spring-jdbc 且存在 DataSource 时启用;否则默认仍是内存向量库。项目提供可选 Liquibase 片段 classpath:/db/changelog/optional/knowledge-pgvector.xml,仅负责结构化创建 knowledge_embedding 表;生产启用前需要在 PostgreSQL 预先安装 pgvector 扩展,HNSW 等向量索引按部署规模由 DBA 或运维脚本单独添加。默认 master changelog 不自动 include 它,避免普通 MySQL / H2 / 未安装 pgvector 的 PostgreSQL 启动失败。
最小启用示例:
spring:
open:
knowledge:
default-vector-store: pgvector
vector-stores:
pgvector:
enabled: true
provider: pgvector
options:
table: knowledge_embedding
vector-column: embedding_vector
metadata-column: metadata_json混合检索
RAG 不建议只依赖向量相似度。更稳的顺序:
- 关键词检索负责精确命中配置 key、类名、路径、错误码。
- 向量检索负责语义相似问题。
KnowledgeManager合并结果、去重、按 score / 来源 / 标题层级排序。Ask仍只返回上下文和 citations,真正生成回答交给 AI Task / AI Model Provider。
切片规则
默认切片器是 Markdown heading-aware:
- 优先按
#/##/###等标题分块 - 保留
headingPath(例Web3 > 支付结算 > 风险审计) - 尽量不拆断代码块
- 单块默认约 800 tokens
- 搜索默认只返回 snippet,减少上下文消耗
知识源约定
| 来源 | 作用 |
|---|---|
.knowledge/ | 默认采集团队知识、FAQ、运营经验和产品知识 |
| 业务来源 contributor | 默认用于用户侧公开业务内容,例如商品、CMS、文章、社区 |
docs/ | 正式开发者文档,默认不采集;仅内部 Agent 场景显式配置 |
.ai/ | AI Agent 长期上下文、计划和决策,默认不采集 |
AGENTS.md | AI Agent 项目入口规则,默认不采集 |
默认不采集:docs/、.ai/**、AGENTS.md、target/、storage/、public/、node_modules/。避免把开发文档、Agent 记忆、执行日志、构建产物和运行文件塞进用户知识检索结果。
与 AI Task 协作
Knowledge 负责「找资料」,AI Task 负责「组织任务」。两者不硬依赖,按场景组合:
AI Task Handler
→ Knowledge.search / Knowledge.ask
→ Pipeline 组装 prompt 或上下文
→ 模型 Provider(后续接入 spring-open-starter-ai-model)
→ 返回结果 / 发送通知 / 写入业务记录使用建议
topK保持克制,默认不把大量文档塞进上下文- 普通搜索优先返回
snippet,需要生成回答时再打开content - citations 应随回答一起保留,方便后台审查和用户追溯来源
docs/、.ai/**、AGENTS.md、构建产物、运行目录不要进入默认知识源
当前边界
| 已具备 | 暂不包含 |
|---|---|
Knowledge facade + KnowledgeManager | 数据库持久化索引 |
| 文件系统来源扫描 | 生产级向量库持久化 |
| Document starter 抽取结果接入 | - |
| Markdown 标题切片 | 外部 embedding 模型默认依赖 |
| 本地 hashing 向量 / hybrid 检索 | - |
| 关键词搜索 | Open Platform 对外开放 API |
| Ask 上下文返回 | 计费 / 配额 |
| - | Knowledge 内置 PDF / Word / Excel / OCR 解析器 |
后续阶段按「Embedding Provider 抽象 → Vector Store 抽象 → pgvector 生产 store → Qdrant 可选 store → AI Task / AI Model 组合」推进。
验证命令
./mvnw -pl spring-open-starters/spring-open-starter-knowledge -am test -DskipITs相关
- AI Task(任务模型):ai-task.md
- Pipeline(管道编排):pipeline.md
- Agent API 接入:ai-agent-api.md
- AI Model 后续规划:
.ai/decisions/adr-032-ai-model-quota.md - Provider 扩展模型:provider.md