Skip to content

知识库与知识管理 ​

知识库是你在 Yuheng 里组织内容的单位:一个知识库装一批相关的资料,并决定这批资料怎么被切分、用哪个向量模型索引、要不要额外生成 Wiki 和知识图谱。库里的每一条内容——一个文件、一个网页 URL、一段手写 Markdown、一组 FAQ——都叫「知识」,上传后会被异步解析成分块并建立索引。

按知识库分而不是全部堆在一起,主要有三个好处:不同资料可以用不同的分块与模型配置;提问时可以只在指定范围内检索;权限和共享也是按库授予的。

0. 日常会用到的操作 ​

想做什么在哪里做
建库、选索引策略知识库编辑弹窗的「基本信息」:勾选「RAG 检索」(向量 + 关键词)和 / 或「Wiki 知识库」。库里已有内容后索引策略锁定,要改须先清空
调分块大小、父子分块知识库编辑弹窗的「分块设置」(见分块机制)
为某类文件换解析引擎知识库编辑弹窗的「解析引擎」(见文档解析服务)
上传文件 / 导入网页 / 手写一篇文档列表页的上传区,或「新建」下拉
用文件夹整理文档文档列表左侧的文件夹树;整目录拖进上传区会保留目录结构(见 §3.4)
给文档打标签(一篇可多个)单篇在详情里改;多篇勾选后用批量操作栏的「标签」(见 §3.5)
检查解析结果、改错字打开文档 → 分块列表 → 直接编辑分块(见 §3.6)
补充部门、密级等自定义字段文档详情里的自定义元数据(见 §3.1)
看谁改过什么知识库编辑弹窗 → 「活动记录」(见 §6)
整库复制 / 把文档挪到别的库知识库列表的复制,或文档批量操作里的移动(见 §4)
指定一篇文档由谁负责、确认它仍然有效打开文档详情,「负责人」「复核」两行(见 §9)
让没人确认的文档定期提醒负责人复核知识库编辑弹窗 → 「基本信息」→「定期复核」,填天数(见 §1.8)
查看重复、有出入、过期、被反馈有误的文档知识库页面顶部的「知识健康」标签(见知识健康)

1. 知识库模型与配置项 ​

1.1 KB 类型 ​

internal/types/knowledgebase.go:

go
const (
    KnowledgeBaseTypeDocument = "document" // 文档类
    KnowledgeBaseTypeFAQ      = "faq"      // FAQ 类
    KnowledgeBaseTypeWiki     = "wiki"     // Wiki 类
)

更新 KB 时会清除与其类型不匹配的配置(如非 FAQ 库的 FAQConfig)。VectorStoreID 使用 GORM <-:create 标签,创建后不可修改(防止索引与存储错位)。

1.2 配置结构总览 ​

1.3 ChunkingConfig(分块配置) ​

字段类型默认说明
chunk_sizeint512(≤0 时取默认)分块大小(字符数)
chunk_overlapint80(≤0 时取默认)相邻分块重叠(字符数);0 不表示「不重叠」,见分块机制 §1.1
separators[]string-分隔符列表
parser_engine_rules[]ParserEngineRule-按文件类型指定解析引擎:{file_types, engine, xlsx_first_row_as_header?}
enable_parent_childboolfalse启用父子分块策略
parent_chunk_sizeint4096父分块大小(用于返回上下文)
child_chunk_sizeint384子分块大小(用于嵌入检索)
strategystring空(= legacy)分块策略:legacy(历史递归切分)/ auto(画像器自动选层)/ heading / heuristic / recursive(固定某一层),详见分块机制
token_limitint0近似 token 上限(0 = 只按 chunk_size 字符数)
languages[]string自动检测语言提示
table_metadata_instructionsstring-表格元数据生成指令

1.4 IndexingStrategy(索引管线开关) ​

字段默认说明
vector_enabledtrue语义向量检索
keyword_enabledtrue关键词(BM25)检索
wiki_enabledfalseWiki 页面生成
graph_enabledfalse知识图谱提取

界面上「RAG 检索」一个勾选同时控制 vector_enabled 与 keyword_enabled;知识图谱在「知识图谱」页签单独开启(需要部署 Neo4j,见知识图谱)。编辑已有内容的知识库时索引策略不可改。

1.5 多模态与富化配置 ​

VLMConfig(视觉语言模型):

字段说明
enabled / model_id新版:启用开关 + 模型 ID
description_language图片描述语言(空 = 跟随文档语言)
custom_instructionsKB 级图片解释指导
model_name / base_url / api_key / interface_type旧版兼容字段(ollama / openai)

启用判定:Enabled && ModelID != "",或旧版 ModelName != "" && BaseURL != ""。

ASRConfig:enabled / model_id / language(语言提示,可选)。

ImageProcessingConfig:model_id。

QuestionGenerationConfig(问题生成):enabled;question_count 每分块生成问题数(默认 3,上限 10);custom_instructions 目标受众 / 风格说明。

ExtractConfig(知识图谱):enabled、text、tags、nodes []*GraphNode{name, chunks, attributes}、relations []*GraphRelation{node1, node2, type}、custom_instructions(领域提取指导)。

AutoTagConfig(自动关联标签,仅文档库):enabled;model_id(留空用知识库的摘要模型);max_tags 单篇最多关联几个标签(默认 3,上限 10);skip_if_tagged 已有标签的文档不再自动打(默认 true)。文档解析完成后,模型从本库已有的标签里挑选合适的关联上,不新建也不删除标签,每篇文档多一次模型调用。界面位置:「高级设置」→「自动关联标签」。

FAQConfig(仅 FAQ 库):index_mode(question_only / question_answer,默认后者)、question_index_mode(combined / separate,默认 combined),详见 FAQ 篇。

WikiConfig(打开 indexing_strategy.wiki_enabled 的知识库)——注意它不是 type = "wiki" 专属:普通文档库打开 Wiki 索引后,UpdateKnowledgeBase 会自动给它建一份空的 WikiConfig 承载这些可调项:

字段默认说明
synthesis_model_id-Wiki 生成 LLM
max_pages_per_ingest0(不限)单次摄入最多创建/更新页面数
extraction_granularitystandardfocused(仅主要主题)/ standard / exhaustive(全部实体概念)
content_instructions / extraction_instructions-生成与提取风格指导
ingest_batch_size / ingest_map_parallel / ingest_reduce_parallel / ingest_max_inflight5 / 10 / 10 / 4摄入并发参数

所有 custom_instructions 类字段在更新时经 validateKnowledgeBasePromptInstructions 校验长度与合法性(internal/handler/knowledgebase.go)。

1.6 存储配置 ​

  • StorageBackendID(必填):新文件写入的存储后端实例,创建时不指定就绑定工作区默认(见存储后端)。它只决定新文件写到哪里:已有文件按各自的资源记录读取,所以有文件的知识库也可以换实例。响应里另带 storage_backend(实例的 id、name、provider、source、is_builtin),只对知识库所属工作区返回。

1.7 KB 计算字段 ​

列表 / 详情响应附带:knowledge_count、chunk_count、is_processing(FAQ 库)、processing_count(文档库处理中知识数)、creator_name、is_pinned / pinned_at(当前用户置顶状态)。

另有一个存储字段 is_temporary:标记临时(ephemeral)知识库,正常的知识库列表里不展示。它由系统内部使用,典型场景是联网搜索把抓回来的网页缓存成可检索内容。手工建库不会产生临时库。

1.8 复核周期(review_interval_days) ​

review_interval_days 规定一篇文档最多可以多少天没人确认、也没人修改;超过后知识健康会生成一条「需要复核」交给文档负责人。默认 0,表示不做定期复核;上限 3650(数据库约束同样限制)。在知识库编辑弹窗的「基本信息」→「定期复核」里设置,或通过 PUT /knowledge-bases/:id 在请求体的 config.review_interval_days 里传(超出 0–3650 返回校验错误)。计时规则、巡检频率与处理方式见知识健康 §1.2。

2. KB 路由与权限 ​

(门禁语义见《工作区、用户与认证授权》篇;KBAccess 要求知识库属于调用者的工作区,别的工作区的知识库返回 404,读写同一个守卫,读写的区别在角色与所有权守卫上。)

方法路径Handler门禁
POST/knowledge-basesCreateKnowledgeBaseContributor+ / API Key manage_kbs
GET/knowledge-basesListKnowledgeBasesViewer+ / retrieve
GET/knowledge-bases/:idGetKnowledgeBaseViewer+ + KBAccess
PUT/knowledge-bases/:idUpdateKnowledgeBaseOwnedKBOrAdmin + KBAccess
DELETE/knowledge-bases/:idDeleteKnowledgeBaseOwnedKBOrAdmin + KBAccess
PUT/knowledge-bases/:id/pinTogglePinKnowledgeBaseViewer+ + KBAccess
POST/knowledge-bases/:id/hybrid-searchHybridSearchViewer+ + KBAccess
POST/knowledge-bases/copyCopyKnowledgeBaseContributor+ / manage_kbs
POST/knowledge-bases/:id/duplicateDuplicateKnowledgeBaseContributor+ / manage_kbs + KBAccess
GET/knowledge-bases/copy/progress/:task_idGetKBCloneProgressViewer+ / retrieve 或 manage_kbs
GET/knowledge-bases/:id/move-targetsListMoveTargetsViewer+ + KBAccess
GET/knowledge-bases/:id/activityListKnowledgeBaseActivityOwnedKBOrAdmin + KBAccess(仅 JWT)

知识健康(/knowledge-bases/:id/findings*)的路由见知识健康 §6。

创建流程(internal/handler/knowledgebase.go):Contributor 校验 → 请求参数校验(图谱抽取配置、各类 custom_instructions 长度)→ 服务层创建(含 VectorStoreID 绑定校验)→ 返回 KB 与向量存储的展示信息。存储配额不在建库时检查,而是在向库里添加内容时检查(见 §7)。

删除(DeleteKnowledgeBase):先软删除 KB 行并记 kb.deleted 活动,同步清理该库排队中的任务、停止并软删除绑定的数据源;随后投递一个异步删除任务,在后台清掉库内知识、分块、检索索引与存储文件。

3. 知识(Knowledge)管理 ​

3.1 模型要点 ​

internal/types/knowledge.go。关键字段:type(manual 手动 Markdown / url / faq / 文件类型)、source(URL 类知识存地址)/ channel(摄入渠道)、parse_status、summary_status、enable_status、file_name/type/size/hash/path、storage_size、metadata(JSON,手动知识存 ManualKnowledgeMetadata{content, format, status(draft/publish), version})、custom_metadata(JSON,用户自填元数据)、last_faq_import_result,以及负责人字段 owner_id / reviewed_at / reviewed_by(migration 000125,见 §9)。

metadata 与 custom_metadata 刻意分开(migration 000078):前者是入库过程写入的内部状态与 ID,后者是用户自己维护的描述性字段(部门、密级、版本号等)。custom_metadata 最多 20 个字段,键 1-64 字符,值为字符串/数字/布尔/null 且不超过 1000 字符;Knowledge.CustomMetadataText() 把它渲染成稳定排序的 键: 值 文本,参与摘要生成与文档级模型上下文。修改元数据会自动触发一次摘要刷新。

channel 记录内容从哪里进来:界面上传默认 web;上传接口可用表单字段 channel 自报(如 api);数据源同步写入连接器类型(feishu、feishu_drive、lark_drive、notion、yuque、rss、gitlab、ima);在线文档页面的镜像为 docs。channel 是自由文本:上游 IM 集成(已移除)写入的 wechat、wecom、dingtalk、slack、im 仍可能出现在旧数据里,只用于显示和过滤,不需要迁移;现在的代码不会再产生这些值。

解析状态机:

摘要独立状态:summary_status ∈ {none, pending, processing, completed, failed}。

3.2 知识路由 ​

方法路径说明门禁
POST/knowledge-bases/:id/knowledge/file上传文件OwnedKBOrAdmin + KBAccess
POST/knowledge-bases/:id/knowledge/urlURL 导入同上
POST/knowledge-bases/:id/knowledge/manual手动 Markdown 知识同上
GET/knowledge-bases/:id/knowledge列表(分页 + 过滤)Viewer+ + KBAccess
DELETE/knowledge-bases/:id/knowledge清空 KB 内容Admin + KBAccess
GET/knowledge/:id、/knowledge/batch详情 / 批量获取Viewer+
GET/knowledge/:id/stages、/knowledge/:id/spans处理阶段 / 跨度Viewer+
PUT / DELETE/knowledge/:id、/knowledge/manual/:id更新(含 custom_metadata)/ 删除OwnedKnowledgeKBOrAdmin + KBAccess
POST/knowledge/:id/reparse、/knowledge/:id/cancel-parse重解析 / 取消解析同上
POST/knowledge/:id/regenerate-summary重新生成文档摘要同上
GET/knowledge/:id/download下载原始文件Contributor+ + KBAccess
GET/knowledge/:id/preview预览文件Viewer+ + KBAccess
PUT/knowledge/tags批量更新标签Contributor+ / ingest
POST/knowledge/batch-reparse、/knowledge/batch-delete批量重解析 / 删除Contributor+ / ingest
POST/knowledge/move移动知识Contributor+ / ingest
GET/knowledge/move/progress/:task_id移动进度Viewer+
POST/knowledge/folder把文档移到文件夹(只改归类)Contributor+ / ingest
GET/knowledge/:id/stewardship负责人、最近确认、复核到期时间Viewer+ + KBAccess
PUT/knowledge/:id/owner转交负责人OwnedKnowledgeKBOrAdmin + KBAccess
POST/knowledge/:id/review确认文档仍然有效(需要登录用户,API Key 不行)同上

3.3 列表过滤参数 ​

internal/types/knowledge.go 的 KnowledgeListFilter + internal/handler/knowledge.go:

参数说明
page / page_size分页(按 created_at DESC 排序)
keyword按文件名 / 标题搜索
file_type文件类型过滤(pdf …;manual / url 按知识的 type 列匹配)
parse_status解析状态过滤
source摄入渠道过滤(api / web / feishu …)
tag_ids标签过滤,逗号分隔多个(OR 语义)
start_time / end_time按 updated_at 过滤的时间范围(RFC3339,或 2006-01-02 15:04:05 / 2006-01-02,按服务器时区解析)
folder_path按文件夹筛选。是否传这个参数决定列表模式:不传是全库扁平视图,传空字符串是知识库根目录(不含子目录)
folder_recursive配合 folder_path 使用,为 true 时连子目录里的文档一起返回

3.4 文件夹树 ​

文档多了之后平铺列表不好找,知识库因此支持树形文件夹,像文件管理器一样组织内容。

怎么用:

  • 整目录拖进上传区:目录结构会被原样保留,不需要事后手工建文件夹;
  • 新建 / 重命名 / 移动文件夹:文档列表左侧的文件夹树上操作。重命名会连子目录一起改路径;目标路径已存在时两个文件夹合并;不允许把文件夹移到自己的子目录下;
  • 重新归类文档:勾选文档后移动到指定文件夹(也可以移回根目录)。这只改归类,不重新解析、不影响索引;
  • 按目录浏览:列表接口的 folder_path 决定视图模式——不传是全库平铺,传空字符串是根目录(不含子目录),配 folder_recursive=true 则连子目录一起列。

文件夹与标签解决的是不同问题,可以叠加使用:文件夹是唯一归属(一篇文档只在一个目录下,适合按项目/来源归档),标签是多对多(一篇文档可带多个标签,适合按主题、密级、状态交叉筛选)。检索时两者都能作为范围限定条件。

实现上,整个目录拖进上传区时,目录结构会被保留下来:路径存在 knowledges.folder_path 列(migration 000079),file_name 只留文件名。早期版本把相对路径塞在 file_name 里,导致列表标题显示成一长串路径且无法按目录查询,迁移时已自动回填。

界面上文档列表左侧是文件夹树,可以像文件管理器一样浏览、重命名文件夹、把文档拖到别的文件夹。对应接口是 GET/PUT /knowledge-bases/:id/knowledge/folders 与 POST /knowledge/folder(见 API 参考)。重命名文件夹会连子目录一起改路径,目标已存在时两个文件夹合并。

3.5 标签(KnowledgeTag) ​

internal/types/tag.go + internal/handler/tag.go:

go
type KnowledgeTag struct {
    ID              string // UUID
    SeqID           int64  // 自增整数 ID(API 使用)
    TenantID        uint64
    KnowledgeBaseID string
    Name            string // KB 内唯一
    Color           string
    SortOrder       int
}
type KnowledgeTagRelation struct { KnowledgeID, TagID string } // 多对多

一篇文档可以带多个标签。 早期是单标签(knowledges.tag_id 一列),migration 000063 换成了关联表 knowledge_tag_relations:建表时把原有的单标签数据迁进去,然后删掉了 knowledges.tag_id 列。所以现在:

  • 读:Knowledge.Tags 是查询时按 knowledge_id 批量 JOIN 出来的(gorm:"-",不落在 knowledges 表上);
  • 写:整体替换语义——PUT /knowledge/tags 传 {knowledge_id: [tag_ids]},实现先删该文档的全部关联再写入新集合;
  • 过滤:列表参数 tag_ids 是 OR 语义(命中任一标签即返回),SQL 走 knowledges.id IN (SELECT knowledge_id FROM knowledge_tag_relations WHERE tag_id IN (...));
  • FAQ 条目是另一套:它本身是 chunk,标签存在 chunks.tag_id 上(单标签),与文档的多标签关联表不是同一条路径。

标签本身的管理路由:GET /knowledge-bases/:id/tags(Viewer+)、POST(OwnedKBOrAdmin)、PUT/DELETE /knowledge-bases/:id/tags/:tag_id(OwnedKBOrAdmin);tag_id 路径参数同时接受 UUID 与整数 seq_id。

前端两个入口:

  • 批量打标签:文档列表勾选若干文档后,批量操作栏的「标签」按钮打开 BatchTagDialog.vue。对话框会把所选文档共有的标签预选中,支持搜索、直接跳转标签管理,提交后刷新列表;
  • 上传时设置标签:上传确认对话框(UploadConfirmDialog.vue)可在文件入库前直接指定标签与解析选项,省去先传后改。

3.6 分块编辑与版本历史 ​

解析结果不总是完美——表格错行、OCR 串字、公式丢符号。这类问题以前只能重传文档,现在可以在文档详情里直接改分块正文,改完立即重建索引,并且每次修改都留有历史版本可以回滚。

实现上(internal/application/service/chunk.go,migration 000078):

数据模型:

字段 / 表作用
chunks.source_content解析器原始输出,不可变。历史行在首次手工编辑时从 content 惰性回填
chunks.content当前生效内容(检索、引用展示都用它)
chunks.content_revision每次编辑或回滚 +1,用作乐观锁
chunks.index_statusready / processing / failed,标识当前内容是否已反映到检索存储
chunks.last_editor_id产生当前版本的操作者
chunk_revisions 表被覆盖的历史版本快照(内容、启停、编辑者、来源、时间)

行为要点:

  • 只有 text 类型分块可编辑;内容去空白后不能为空,上限 200000 字节;
  • 乐观并发:请求可带 expected_revision,与当前版本不符返回 409,前端提示刷新后重试;
  • 不能新增图片:编辑内容中出现源内容里没有的图片 URL 会被拒绝;删除某张图片的 Markdown 引用时,对应的 OCR / caption 子分块被停用而非硬删除,这样回滚历史版本可以把它们重新启用;
  • 父子分块一致性:编辑子块后按偏移量把改动叠加回父块(父块的 source_content 保持不可变,替换按倒序应用,长度变化不会打乱坐标系);
  • 索引失败不假装成功:重建索引失败时行照常保存,但 index_status = failed,界面据此提示;再次提交相同内容会触发重试;
  • 生成问题不丢:内容编辑后原有的检索问题保留,只是被标记为「与当前正文版本不匹配」,可以单条改写(PUT /chunks/by-id/:id/questions)或整体重新生成(POST /chunks/by-id/:id/questions/regenerate);
  • 摘要联动:内容或启停状态变化会入队一次文档摘要刷新,summary_status 转为 pending;也可以用 POST /knowledge/:id/regenerate-summary 手动触发。

回滚(POST /chunks/:knowledge_id/:id/revert)本身也是一次新编辑:目标历史版本的内容被写为当前内容,版本号继续递增,原内容进入历史列表,因此「回滚的回滚」同样可行。

接口清单见 API 参考:分块与标签。

3.7 下载与预览安全 ​

GET /knowledge/:id/preview 按文件名决定响应方式(secutils.SafeContentTypeByFilename):

文件类型响应目的
浏览器会当作页面或脚本执行的类型(.svg .svgz .html .htm .xhtml .xml .js .mjs .css)Content-Type: application/octet-stream + Content-Disposition: attachment不让上传的 HTML/SVG 在本站源下执行(防存储型 XSS)
其他类型(PDF、图片、CSV 等)按扩展名给出真实 Content-Type,Content-Disposition: inline,可在浏览器内预览
所有响应X-Content-Type-Options: nosniff、Cache-Control: private, max-age=3600禁止 MIME 嗅探绕过;不进共享缓存

internal/handler/knowledge_preview_security_test.go 固化了这一点:内容是 <script>alert(1)</script> 的 HTML 文件只会作为附件下载。

下载原始文件(GET /knowledge/:id/download)比预览更严:要求 Contributor+——工作区 Viewer 不能下载原件。

4. 知识库复制与知识移动 ​

4.1 复制(Copy / Duplicate)与 Preflight ​

internal/application/service/knowledge_clone_move.go,preflight 规则由 internal/handler/knowledgebase_copy_preflight_test.go 固化:

  • POST /knowledge-bases/copy:整库复制(配置 + 内容),body 传 source_id,可选 target_id 复制进已有的库;异步任务,进度查 GET /knowledge-bases/copy/progress/:task_id(活动流记 kb.clone_started / kb.clone_completed / kb.clone_failed)。
  • POST /knowledge-bases/:id/duplicate:仅复制配置(不复制内容 / 索引 / 共享记录),活动流记 kb.duplicated。

Preflight(复制前在 handler 里同步校验,不通过直接返回,异步任务里还会再查一遍):

  1. 源 KB 存在,且属于调用者的租户(跨租户返回 403);
  2. 指定了 target_id 时:目标 KB 存在且属于调用者的租户;两库 embedding 模型相同(否则向量工作区不兼容);绑定同一个向量存储(SharesStoreWith);使用同一个存储后端实例(SharesStorageBackendWith,比较具体实例而不只是 provider 类型);
  3. API Key 调用时源 / 目标 KB 均须在 allow-list 内。

4.2 知识移动门禁(move gate) ​

POST /knowledge/move 支持两种模式,约束在 handler 与 service 双层校验(internal/handler/knowledge_move_gate_test.go 与 internal/application/service/knowledge_move_gate_test.go 双重佐证):

  • reuse_vectors 模式:直接复用既有向量,要求源 KB 与目标 KB 绑定同一 VectorStore;
  • reparse 模式:目标库重新解析生成向量,允许跨向量库移动。

同库判定 SharesStoreWith() 的规范化语义(空字符串归一化为 nil,nil 表示环境默认 store):

text
nil & nil               → true   (同为 env-store)
"" & nil                → true   (空串规范化为 nil)
"store-a" & "store-a"   → true
"store-a" & "store-b"   → false
"store-a" & nil         → false  (显式绑定 vs env-store 不视为同库)

GET /knowledge-bases/:id/move-targets 返回符合门禁的候选目标库;移动为异步任务,进度查 GET /knowledge/move/progress/:task_id。

5. 知识处理管线 ​

internal/application/service/knowledge_create.go / knowledge_process.go / knowledge_process_config.go:

text
上传 (file/url/manual)
  → 创建 Knowledge (parse_status=pending) → Asynq 入队
  → Worker: DocReader 解析 → 分块 (ChunkingConfig)
      → 向量嵌入        (indexing_strategy.vector_enabled)
      → 关键词索引       (keyword_enabled)
      → 图谱提取        (graph_enabled + ExtractConfig)
      → Wiki 生成       (wiki_enabled + WikiConfig)
      → 问题生成        (QuestionGenerationConfig.enabled)
  → parse_status=finalizing, pending_subtasks_count=N
  → 每个富化子任务完成后原子递减;归零 → parse_status=completed

配置合并(ResolveProcessConfig → EffectiveProcessConfig):以 KB 配置为底,叠加单次上传的覆盖项(KnowledgeProcessOverrides,存于知识 metadata,可覆盖 parser 规则 / 分块 / 多模态 / ASR / 问题生成 / 图谱开关等;上传确认对话框里的选项就落在这里)。重新解析时沿用上次的覆盖项。

解析完成后还有几类异步后处理:CSV / Excel 额外生成表格摘要分块(table_summary / table_column,用 DuckDB 读表);开启了自动关联标签的文档库做一次标签分类;索引完成约 30 秒后跑知识健康检测(见知识健康 §3)。

Chunk 类型(internal/types/chunk.go):text、parent_text、image_ocr、image_caption、summary、entity、relationship、faq、web_search、table_summary、table_column、wiki_page;chunk 支持 is_enabled 开关与 flags 位标志(bit0 = 可推荐)。

6. 知识库活动流(KB Activity) ​

活动流回答「这个库最近被谁改了什么」:建库改配置、上传删除与重新解析文档、移动文档、标签增删改、共享给谁、数据源同步、FAQ 导入、Wiki 内容变化、转交负责人与确认有效、知识健康问题的忽略 / 指派 / 取代,都会留痕。手工编辑分块不单独记活动,它的历史在分块版本里(§3.6)。入口在知识库编辑弹窗的「活动记录」,只有知识库创建者或 Admin 可见。

internal/application/service/kb_activity.go 复用审计日志体系(AuditLog,scope 为 knowledge_base),通过 recordKBActivity(ctx, audit, tenantID, kbID, action, targetType, targetID, outcome, details) 记录:

  • 活动动作(internal/types/audit_log.go):kb.created / kb.updated / kb.deleted / kb.duplicated / kb.clone_*;knowledge.created / updated / deleted / batch_deleted / reparse_started / parse_canceled / move_* / owner_changed / reviewed;tag.*;kb.share_*;datasource.*;faq.import_*;wiki.content_changed;finding.status_changed / scan_requested / assigned / superseded;
  • 触发源:context 中的 kbActivityTaskMetadata{TaskID, Trigger}(user 用户操作 / system 后台任务)自动并入 details;根据 outcome 自动补 processing_status(accepted→pending、success→completed、partial→partial、failed/denied→failed、canceled→canceled);
  • 批量操作样本标题:kbActivityAppendSampleTitles 为批量操作附带最多 5 个去重标题(第一个作为 title,其余进 titles 数组),保证活动流可读且有界;
  • 抑制机制:withKBActivitySuppressed(ctx) 可让内部级联操作不产生重复活动记录。

查询端点:GET /knowledge-bases/:id/activity(OwnedKBOrAdmin,仅 JWT 用户,API Key 不可访问)。

7. 存储配额与用量 ​

配额挂在租户上(internal/types/tenant.go):

字段默认说明
storage_quota10737418240(10GB)租户总配额
storage_used0已用量(涵盖原始文件、文本、向量与索引占用)

添加知识(文件、URL、手动 Markdown)前检查配额(internal/application/service/knowledge_create.go):storage_quota > 0 且已用量 storage_used 已达到配额时拒绝写入;配额 ≤ 0 表示不限。检查看的是已用量,不预估本次文件大小,所以最后一次上传可能让用量略超配额。每条知识记录自身 file_size 与 storage_size,删除时回收用量。

新建租户的默认配额由系统设置 tenant.default_storage_quota_gb / 环境变量 YUHENG_TENANT_DEFAULT_STORAGE_QUOTA_GB 决定(默认 10GB),在创建时写入租户行,之后改设置不影响已有租户。

POST /knowledge-bases/:id/hybrid-search(internal/handler/knowledgebase.go + internal/application/service/knowledgebase_search*.go)按 KB 的 IndexingStrategy 组合召回:向量(vector_enabled)+ 关键词 BM25(keyword_enabled),两路都有结果时用 RRF 加权融合,只有一路时按原始分去重;结果截断到 match_count(未传或 ≤0 时取 50)。这个端点只做召回与融合,不调用 rerank 模型;重排、知识图谱增强都发生在问答流水线里(见检索问答流程)。多 KB 场景由 knowledgebase_search_fanout.go 并发扇出、knowledgebase_search_fusion.go 融合;共享 KB 检索路径见 knowledgebase_search_shared.go。FAQ 库检索有专门的命中策略(负例过滤 / 迭代召回),见 FAQ 能力。引擎层细节见检索引擎与向量存储。

9. 负责人与复核(Stewardship) ​

每篇文档有一个负责人(owner_id):默认是添加它的人,可以转交。负责人不是权限,谁能看、谁能改仍由上文的角色与共享规则决定;它回答的是「这篇出了问题该找谁」。每篇文档还记录最近一次有人经手(reviewed_at / reviewed_by):有人点「确认仍然有效」或修改了内容时更新;重新解析、换向量模型、移动都不算。

界面上,打开文档详情可以看到「负责人」与「复核」两行:

  • 转交:知识库创建者或 Admin 可以把负责人转给另一位成员,新负责人必须能编辑这个知识库。在线文档页面镜像来的条目,负责人在页面上改,这里显示「在文档页面上修改」(接口返回 409);
  • 确认仍然有效:重新开始复核计时。知识库开启了复核周期(§1.8)时,这一行还显示到期时间和是否已超期;未开启时显示「本知识库未开启定期复核」。

负责人决定知识健康发现的问题派给谁,复核周期决定何时提醒复核。这两件事的完整规则——派发顺序、「我的知识待办」、忽略与取代——见知识健康。

实现参考 ​

想读源码时按下表定位(路径相对仓库根目录):

层文件
KB 模型与配置结构internal/types/knowledgebase.go、indexing_strategy.go
知识 / Chunk / 标签模型internal/types/knowledge.go、chunk.go、tag.go
处理配置覆盖internal/types/knowledge_process.go
KB Handlerinternal/handler/knowledgebase.go
知识 Handlerinternal/handler/knowledge.go
标签 Handlerinternal/handler/tag.go
KB 服务internal/application/service/knowledgebase.go
知识创建 / 处理管线internal/application/service/knowledge_create.go、knowledge_process.go、knowledge_process_config.go
复制与移动internal/application/service/knowledge_clone_move.go
活动流internal/application/service/kb_activity.go
负责人与复核internal/application/service/knowledge_stewardship.go、internal/handler/knowledge_stewardship.go、frontend/src/components/findings/KnowledgeStewardship.vue
知识健康internal/application/service/knowledge_findings.go、internal/handler/knowledge_finding.go、frontend/src/views/knowledge/health/
编辑弹窗frontend/src/views/knowledge/KnowledgeBaseEditorModal.vue、frontend/src/views/knowledge/settings/
路由与门禁internal/router/router.go、internal/router/rbac.go
关键测试佐证internal/handler/knowledge_preview_security_test.go、knowledge_move_gate_test.go、knowledgebase_copy_preflight_test.go

基于 Yuheng v0.1.0 源码整理 · MIT License