Skip to content
bitzorcas
中EN

Reference

AIManage 技能、RAG 与 Agent 适配器

区分持久技能与文件技能,解释 Semantic Kernel、RAG 和 Agent 端口的注册与真实消费边界,避免把元数据误写成已可执行工具。

Last updated

AIManage 中“技能”有两套并行机制:租户持久化的技能元数据,以及 Host 文件系统中的 Markdown 提示词文件。它们目前都没有接入 SendMessage/StreamMessage,也不存在反射调用或 Semantic Kernel tool registration,因此不能描述为“模型已经可以调用业务技能”。

1. 两类技能不要混为一谈

维度持久技能 AISkill文件技能 FileSkillDefinition
作用域TenantId整个进程/部署
存储数据库AI_SKILLS_PATH 或 AI/Skills/*.md
字段HandlerType、Method、Schema、Enabledname/category/description/body
APIregister/list/deletelist/reload
权限Mediator ai/skill仅组级认证
执行当前没有当前没有
热更新数据库下一次查询FileSystemWatcher 500ms 防抖

2. 持久技能注册

注册技能元数据
POST /api/ai/skills
Content-Type: application/json
{
"name": "CreateTicket",
"description": "创建服务工单",
"category": "Support",
"handlerType": "Acme.Support.CreateTicketHandler, Acme.Support",
"handlerMethod": "ExecuteAsync",
"parameterSchemaJson": "{\"type\":\"object\",\"required\":[\"title\"]}"
}

Handler 只校验 Name 和 HandlerType 非空,然后保存字符串。没有验证程序集可加载、类型存在、方法签名、JSON Schema 合法、调用者对目标业务资源的权限、参数安全或返回类型。List 只返回摘要,Registry 查询启用项;Delete 实际是注销/禁用语义,以 Registry 实现为准。

3. 文件技能格式与扫描

AI/Skills/contract-review.md
---
name: ContractReview
category: LegalOps
description: 识别合同中的履约风险
---
你是合同复核助手。只输出风险、依据和需要人工确认的问题。

扫描器用一个简单正则拆 front matter,再按行正则读取三个字段;它不是完整 YAML parser。正文为空时回退为 description。相同 Name 后加载的文件覆盖前项,列表顺序没有稳定保证。

启动 Start() 时扫描并创建 FileSystemWatcher。若目录启动时不存在,watcher 不会启动;手工 reload 只扫描,也不会立即 StartWatching。只有 timer 回调在 watcher 为 null 时尝试重建,因此“之后才创建目录”不一定自动被发现。文件系统事件可能丢失,Error 时 1 秒后重建。

文件列表/重载端点绕过 IAuthorizedRequest,任意认证用户都可查看文件名、描述和时间,并触发全进程重扫。GA 前应限制为运维/技能管理员,避免暴露部署文件结构与形成 DoS 面。

4. Semantic Kernel 不是自动 Agent

当前 SemanticKernelAdapter 只做聊天消息和执行参数转换。虽然公开 Kernel 属性供高级场景获取,但主路径没有添加 Plugin、KernelFunction、ToolCallBehavior,也没有逐工具授权、确认或审计。

一个安全工具执行闭环至少需要:

  1. 服务器 allowlist 解析工具,不信任模型给出的类型名;
  2. 每次调用重新执行租户、用户和目标资源授权;
  3. JSON Schema 验证、大小/枚举/格式限制;
  4. 只把最少参数与最少结果暴露给模型;
  5. 对写操作要求显式确认和稳定幂等键;
  6. 记录 request、tool、policy、actor、target、result 和耗时,不记录 Secret;
  7. 限制递归轮数、并发、Token、超时和总费用;
  8. 禁止自动重放有副作用调用。

5. RAG 端口

IRagSearchPort 提供 HybridSearch、GetSystemPrompt、IndexDocument 和 EnsureCollection。Application 默认注册 UnavailableRagSearchPort,生产只有在 AIManage:Provider 非空且非 None、并且连接器服务已注册时,Infrastructure 才 Replace 为 RagServiceAdapter。

missing / Noneconfigured + SDK services当前无调用

Host composition

AIManage:Provider?

UnavailableRagSearchPort
throws / fails closed

RagServiceAdapter

IRAGService

IQdrantService

SendMessage / StreamMessage

RagServiceAdapter 将连接器 DTO 缩窄成平台结果,这是正确的隔离方向。但 GetSystemPromptAsync、IndexDocumentAsync 和集合创建的部分底层调用没有传播 cancellation token;EnsureCollection 通过异常消息包含 already exists/已存在 判断幂等,容易受 SDK 文案变化影响。

6. Agent 端口

IAgentServiceAdapter 同样默认 Unavailable。生产适配器包装外部 IAgentService:ChatInSessionAsync 管理持久会话,StreamMessageAsync 只透传流并明确不自动保存历史。注释提到 Guidance 可切换到它,但当前只提供桥,不代表 Guidance 或 AIManage 主聊天已使用。

SessionId 的租户隔离由调用方负责。建议强制结构化 SessionKey,而不是文档建议的字符串拼接;Store 谓词仍应绑定 TenantId,不能把 tenant|user|route 约定当安全边界。

7. RAG 数据安全

RAG 不是“把文档塞进向量库”这么简单。落地前必须定义:集合按租户还是按数据域隔离、metadata filter 是否由服务端强制、源文档权限如何在检索时重新验证、删除/权限变更如何传播到索引、Embedding Provider 是否允许接收该分类数据,以及检索片段如何标记为不可信内容防止 Prompt Injection。

GA 目标:服务端强制检索范围
// 调用方只传业务查询;TenantId 与访问范围由服务端上下文生成。
var scope = await ragScope.ResolveAsync(currentUser, resourceIds, cancellationToken);
var results = await rag.HybridSearchAsync(
collectionName: scope.Collection,
queryText: query,
topK: Math.Min(topK, 20),
metadataFilter: scope.RequiredFilter,
cancellationToken);
// 返回模型前仍要逐条执行资源授权和内容分级。

8. 能力成熟度

能力当前状态可宣称口径
租户技能目录已持久化可管理元数据
文件提示词目录进程内扫描可查看/热重载提示词文件
工具执行未实现不可宣称
Semantic Kernel chat已接线文本聊天适配
RAG bridge条件注册可供显式消费者调用
Chat 自动 RAG未实现不可宣称
Agent bridge条件注册可供显式消费者调用
多 Agent 编排未实现不可宣称

9. 测试缺口

现有测试验证 RAG/Agent 参数转发和 fail-closed 组合。还需补:文件技能权限、目录创建/丢事件/重复名、恶意 front matter、路径与大文件、技能 schema、工具逐次授权、跨租户 RAG、索引删除同步、Prompt Injection、取消传播、连接器错误类型和端到端 Chat/RAG/Tool 路径。

AIManage 总览 · 流式与用量 · 测试与 GA

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%