diff --git a/docs/agent-skills-search/agent_teams/01-architecture-design.md b/docs/agent-skills-search/agent_teams/01-architecture-design.md new file mode 100644 index 00000000..0f9e2e92 --- /dev/null +++ b/docs/agent-skills-search/agent_teams/01-architecture-design.md @@ -0,0 +1,674 @@ +# Agent+Skill 检索系统架构设计 + +## 1. 系统概述 + +### 1.1 设计目标 + +构建一个基于 PostgreSQL + pgvector 的智能技能检索系统,通过意图识别、多轮对话上下文、场景描述、用户角色、标签和元数据等多维度信息,为 Agent 精准匹配适合的 Skills。 + +### 1.2 核心能力 + +- **语义理解**:基于向量嵌入的语义相似度检索 +- **意图识别**:识别用户查询的真实意图类别 +- **上下文感知**:结合多轮对话历史,理解用户当前需求 +- **场景适配**:根据使用场景和用户角色推荐技能 +- **多维度融合**:综合向量、意图、标签、流行度、评分等多维度评分 + +## 2. 系统分层架构 + +### 2.1 整体分层 + +```mermaid +graph TB + subgraph "表现层 (Presentation Layer)" + A1[REST API Gateway] + A2[WebSocket Gateway
实时对话] + end + + subgraph "应用层 (Application Layer)" + B1[Agent Skill Search Controller] + B2[Agent Session Controller] + B3[Skill Embedding Sync Controller] + end + + subgraph "服务层 (Service Layer)" + C1[Context Builder
上下文构建器] + C2[Intent Classifier
意图分类器] + C3[Query Embedder
查询向量化] + C4[Hybrid Search Service
混合检索服务] + C5[Skill Reranker
技能重排序器] + C6[Agent Session Service
会话管理服务] + C7[Embedding Sync Service
嵌入同步服务] + end + + subgraph "领域层 (Domain Layer)" + D1[Agent Session] + D2[Agent Message] + D3[Skill Embedding] + D4[Intent Mapping] + D5[Search Context] + D6[Match Result] + end + + subgraph "基础设施层 (Infrastructure Layer)" + E1[(PostgreSQL
+ pgvector)] + E2[(Redis Cache)] + E3[OpenAI Embedding API] + E4[Message Queue
异步处理] + end + + A1 --> B1 + A1 --> B2 + A1 --> B3 + A2 --> B2 + + B1 --> C1 + B1 --> C4 + B2 --> C6 + B3 --> C7 + + C1 --> C6 + C1 --> D5 + C2 --> D4 + C3 --> E3 + C4 --> C3 + C4 --> C2 + C4 --> C5 + C6 --> D1 + C6 --> D2 + C7 --> D3 + + C1 --> E2 + C2 --> E2 + C4 --> E1 + C5 --> E1 + C6 --> E1 + C6 --> E2 + C7 --> E4 + + style A1 fill:#e1f5ff + style A2 fill:#e1f5ff + style E3 fill:#ffebee + style E1 fill:#c8e6c9 + style E2 fill:#fff9c4 +``` + +### 2.2 分层职责 + +| 层级 | 职责 | 核心组件 | +|------|------|----------| +| 表现层 | 暴露 API,处理请求响应 | REST API、WebSocket | +| 应用层 | 编排业务流程,处理应用逻辑 | Controller、DTO | +| 服务层 | 核心业务逻辑实现 | 各种 Service | +| 领域层 | 领域模型和业务规则 | Entity、Domain Object | +| 基础设施层 | 数据持久化、外部服务调用 | 数据库、缓存、API | + +## 3. 核心模块设计 + +### 3.1 模块关系图 + +```mermaid +graph TD + subgraph "输入模块" + IN1[Query Input] + IN2[Session Context] + IN3[User Context] + end + + subgraph "处理模块" + P1[Context Builder] + P2[Intent Classifier] + P3[Query Embedder] + P4[Hybrid Search] + P5[Reranker] + end + + subgraph "存储模块" + S1[Skill Embeddings] + S2[Intent Mapping] + S3[Session Store] + end + + subgraph "输出模块" + OUT1[Ranked Skills] + OUT2[Match Reasons] + OUT3[Confidence Scores] + end + + IN1 --> P1 + IN2 --> P1 + IN3 --> P1 + P1 --> P2 + P1 --> P3 + P2 --> P4 + P3 --> P4 + P4 --> S1 + P4 --> S2 + P5 --> P4 + P4 --> P5 + P5 --> OUT1 + P5 --> OUT2 + P5 --> OUT3 + P1 --> S3 + + style IN1 fill:#e1f5ff + style S1 fill:#c8e6c9 + style OUT1 fill:#c8e6c9 +``` + +### 3.2 模块详细设计 + +#### 3.2.1 Context Builder(上下文构建器) + +**职责**:收集并整合所有上下文信息 + +**输入**: +- 查询文本 +- Session ID +- 用户 ID +- 场景描述(可选) +- 用户角色(可选) +- 元数据(可选) + +**输出**:`AgentSearchContext` + +**核心逻辑**: +1. 从缓存/数据库加载会话历史 +2. 提取最近 N 轮对话作为上下文 +3. 整合用户角色和场景信息 +4. 构建统一的上下文对象 + +#### 3.2.2 Intent Classifier(意图分类器) + +**职责**:识别用户查询的意图类型 + +**实现方式**:基于向量相似度的分类 + +**流程**: +1. 将查询文本转换为向量 +2. 与预定义的意图嵌入计算余弦相似度 +3. 返回 Top-N 意图及置信度 + +**输出**:`IntentClassificationResult` + +#### 3.2.3 Query Embedder(查询向量化) + +**职责**:将综合查询上下文转换为向量 + +**向量融合公式**: +``` +query_vector = normalize( + w1 * embed(query_text) + + w2 * embed(conversation_context) + + w3 * embed(scenario_description) + + w4 * embed(user_role) + + w5 * intent_embedding +) +``` + +**权重配置**: +- w1 (查询文本): 0.4 +- w2 (对话上下文): 0.2 +- w3 (场景描述): 0.15 +- w4 (用户角色): 0.1 +- w5 (意图): 0.15 + +#### 3.2.4 Hybrid Search Service(混合检索服务) + +**职责**:执行多维度检索,综合多种检索策略 + +**检索维度**: +1. 向量检索:pgvector 语义相似度 +2. 意图过滤:基于意图类别过滤 +3. 标签匹配:精确匹配用户指定标签 +4. 权限过滤:根据用户角色过滤可见技能 + +**检索策略**:先向量检索获得候选集,再逐步过滤 + +#### 3.2.5 Skill Reranker(技能重排序器) + +**职责**:对检索结果进行多维度重排序 + +**评分公式**: +``` +final_score = α * vector_similarity + + β * intent_match_score + + γ * tag_match_score + + δ * popularity_score + + ε * rating_score +``` + +**权重配置**: +- α (向量相似度): 0.4 +- β (意图匹配): 0.25 +- γ (标签匹配): 0.2 +- δ (流行度): 0.1 +- ε (评分): 0.05 + +#### 3.2.6 Agent Session Service(会话管理服务) + +**职责**:管理 Agent 对话会话的生命周期 + +**核心功能**: +- 创建新会话 +- 追加对话消息 +- 获取会话历史 +- 会话过期管理 +- 异步持久化 + +## 4. 数据流设计 + +### 4.1 主检索流程 + +```mermaid +sequenceDiagram + participant Client + participant API + participant ContextBuilder + participant IntentClassifier + participant QueryEmbedder + participant HybridSearch + participant Reranker + participant Redis + participant PostgreSQL + + Client->>API: POST /api/agent/skills/search + API->>ContextBuilder: buildContext(request) + ContextBuilder->>Redis: getSession(sessionId) + Redis-->>ContextBuilder: session data + ContextBuilder-->>API: AgentSearchContext + + API->>IntentClassifier: classify(query, context) + IntentClassifier->>PostgreSQL: query intents by vector + PostgreSQL-->>IntentClassifier: top intents + IntentClassifier-->>API: IntentClassificationResult + + API->>QueryEmbedder: embed(query, context, intent) + QueryEmbedder->>Redis: get cached embedding + alt cache miss + QueryEmbedder->>QueryEmbedder: call OpenAI API + QueryEmbedder->>Redis: cache embedding + end + QueryEmbedder-->>API: query_vector + + API->>HybridSearch: search(vector, context, intent) + HybridSearch->>PostgreSQL: vector search with filters + PostgreSQL-->>HybridSearch: candidate skills + HybridSearch-->>API: candidate results + + API->>Reranker: rerank(candidates, context) + Reranker-->>API: ranked results + + API-->>Client: SearchResponse + + Note over API,Redis: async save message + API->>Redis: saveMessage(sessionId, message) +``` + +### 4.2 技能向量同步流程 + +```mermaid +sequenceDiagram + participant SkillService + participant MessageQueue + participant EmbeddingSync + participant OpenAI + participant PostgreSQL + + SkillService->>MessageQueue: publish skill update event + MessageQueue->>EmbeddingSync: consume event + EmbeddingSync->>PostgreSQL: get skill metadata + PostgreSQL-->>EmbeddingSync: skill data + EmbeddingSync->>OpenAI: generate embeddings + OpenAI-->>EmbeddingSync: embedding vectors + EmbeddingSync->>PostgreSQL: upsert embeddings + EmbeddingSync->>PostgreSQL: rebuild vector index + PostgreSQL-->>EmbeddingSync: success +``` + +## 5. 架构图 + +### 5.1 系统架构图 + +```mermaid +C4Context + title Agent+Skill 检索系统架构 + + Person(agent_user, "Agent 用户", "使用 Agent 进行技能搜索") + System(skillhub_system, "SkillHub 系统", "技能注册与发现平台") + System(external_ai, "OpenAI API", "嵌入向量生成服务") + SystemDb(database, "PostgreSQL", "数据持久化与向量检索") + + Rel(agent_user, skillhub_system, "使用", "HTTPS/JSON") + Rel(skillhub_system, external_ai, "调用", "HTTPS") + Rel(skillhub_system, database, "读写", "JDBC") + + System_Boundary(skillhub_boundary, "SkillHub 系统") { + System_Ext(api_gateway, "API Gateway", "REST API 接入层") + System(application, "Application Layer", "业务应用层") + System(service_layer, "Service Layer", "核心服务层") + System(cache, "Redis", "缓存层") + } + + Rel(agent_user, api_gateway, "调用") + Rel(api_gateway, application, "路由") + Rel(application, service_layer, "调用") + Rel(service_layer, cache, "缓存读写") +``` + +### 5.2 容器架构图 + +```mermaid +graph TB + subgraph "用户接入层" + LB[Load Balancer] + end + + subgraph "应用服务层" + GW[API Gateway] + APP1[SkillHub App 1] + APP2[SkillHub App 2] + APP_N[SkillHub App N] + end + + subgraph "数据处理层" + WORKER[Embedding Worker] + end + + subgraph "存储层" + PG[(PostgreSQL Primary)] + PG_REPLICA[(PostgreSQL Replica)] + REDIS[(Redis Cluster)] + MQ[Message Queue] + end + + subgraph "外部服务" + OPENAI[OpenAI API] + end + + LB --> GW + GW --> APP1 + GW --> APP2 + GW --> APP_N + + APP1 --> PG + APP1 --> PG_REPLICA + APP1 --> REDIS + APP2 --> PG + APP2 --> PG_REPLICA + APP2 --> REDIS + APP_N --> PG + APP_N --> PG_REPLICA + APP_N --> REDIS + + APP1 --> MQ + APP2 --> MQ + APP_N --> MQ + + MQ --> WORKER + WORKER --> OPENAI + WORKER --> PG + + PG -.->|Replication| PG_REPLICA + + APP1 --> OPENAI + APP2 --> OPENAI + APP_N --> OPENAI + + style LB fill:#e1f5ff + style PG fill:#c8e6c9 + style REDIS fill:#fff9c4 + style OPENAI fill:#ffebee +``` + +## 6. 可扩展性设计 + +### 6.1 水平扩展 + +| 组件 | 扩展方式 | 说明 | +|------|----------|------| +| 应用服务 | 多实例部署 | 通过负载均衡分发请求 | +| 数据库 | 读写分离 | 主库写入,从库读取 | +| 缓存 | 集群模式 | Redis Cluster 分片存储 | +| 向量索引 | 分区表 | 按技能类别分区 | + +### 6.2 垂直扩展 + +| 资源 | 优化方向 | 说明 | +|------|----------|------| +| CPU | 异步处理 | 嵌入生成异步化 | +| 内存 | 缓存优化 | 热数据缓存 | +| 网络 | 批量请求 | 减少 API 调用次数 | +| 存储 | 索引优化 | ivfflat 参数调优 | + +### 6.3 扩展点 + +1. **嵌入提供者接口**:支持切换不同的嵌入模型 +2. **意图分类器接口**:支持自定义意图分类逻辑 +3. **重排序策略接口**:支持业务特定的排序规则 +4. **过滤器插件接口**:支持添加自定义过滤逻辑 + +## 7. 可靠性设计 + +### 7.1 故障处理策略 + +| 故障场景 | 处理策略 | 降级方案 | +|----------|----------|----------| +| OpenAI API 调用失败 | 重试 3 次,指数退避 | 使用本地哈希向量 | +| 向量索引不可用 | 记录告警,使用全文搜索 | 基于关键词检索 | +| 意图识别失败 | 使用默认意图 "general" | 无降级 | +| 数据库连接失败 | 切换到只读副本 | 返回缓存结果 | +| Redis 不可用 | 直接查询数据库 | 稍微增加响应时间 | +| 消息队列不可用 | 同步处理嵌入 | 稍微增加发布时间 | + +### 7.2 数据一致性 + +| 场景 | 策略 | +|------|------| +| 会话消息保存 | 写后读一致性 | +| 嵌入向量更新 | 最终一致性 | +| 缓存更新 | Write-Through | +| 搜索索引更新 | 异步重建 | + +### 7.3 容灾设计 + +- 数据库定期备份(每日全量 + 每小时增量) +- Redis AOF 持久化 + RDB 快照 +- 应用服务多可用区部署 +- 关键接口重试机制 + +## 8. 性能设计 + +### 8.1 性能目标 + +| 指标 | 目标值 | +|------|--------| +| P95 查询响应时间 | < 500ms | +| P99 查询响应时间 | < 1000ms | +| 并发 QPS | > 100 | +| 支持 Agent 数量 | > 1000 | +| 单会话消息数 | > 1000 | +| 技能库规模 | > 10000 | + +### 8.2 性能优化策略 + +1. **缓存策略** + - 活跃会话:Redis 缓存,TTL 1 小时 + - 意图嵌入:Redis 缓存,永久 + - 技能嵌入:PostgreSQL 存储,版本更新时失效 + - 查询结果:Redis 缓存,TTL 5 分钟 + +2. **数据库优化** + - 向量索引:ivfflat,lists = sqrt(行数) + - 查询优化:限制候选集大小 + - 连接池:合理配置连接池大小 + +3. **异步处理** + - 嵌入生成:异步处理 + - 会话消息保存:异步持久化 + - 指标收集:异步上报 + +4. **批量操作** + - 批量向量生成 + - 批量数据库写入 + - 批量缓存更新 + +## 9. 安全设计 + +### 9.1 安全层次 + +```mermaid +graph TB + subgraph "网络安全" + N1[TLS/HTTPS 加密传输] + N2[防火墙规则] + end + + subgraph "应用安全" + A1[身份认证
JWT/OAuth2] + A2[权限控制
RBAC] + A3[输入验证] + A4[输出编码] + end + + subgraph "数据安全" + D1[SQL 注入防护] + D2[敏感数据加密] + D3[访问审计] + end + + subgraph "API 安全" + API1[速率限制] + API2[API Key 管理] + API3[请求签名] + end + + N1 --> A1 + A1 --> A2 + A2 --> D1 + D1 --> API1 + + style A1 fill:#fff9c4 + style D1 fill:#ffebee +``` + +### 9.2 安全措施 + +| 安全领域 | 措施 | +|----------|------| +| 认证 | JWT Token,有效期 1 小时 | +| 授权 | 基于角色的访问控制 (RBAC) | +| 加密 | HTTPS 传输,数据库字段加密 | +| 审计 | 记录关键操作日志 | +| 限流 | 用户级别 + IP 级别限流 | +| 输入验证 | 所有输入参数校验 | + +## 10. 监控与可观测性 + +### 10.1 监控指标 + +| 类别 | 指标 | +|------|------| +| 业务 | 搜索请求量、Top-10 准确率、意图识别准确率 | +| 性能 | 响应时间 P50/P95/P99、QPS、错误率 | +| 系统 | CPU 使用率、内存使用率、磁盘 I/O | +| 数据库 | 连接数、查询耗时、慢查询数 | +| 缓存 | 命中率、内存使用、键数量 | + +### 10.2 日志策略 + +| 日志类型 | 级别 | 内容 | +|----------|------|------| +| 访问日志 | INFO | 请求/响应摘要 | +| 业务日志 | INFO | 关键业务操作 | +| 错误日志 | ERROR | 异常堆栈 | +| 审计日志 | WARN | 敏感操作 | + +### 10.3 告警规则 + +| 场景 | 阈值 | 级别 | +|------|------|------| +| P95 响应时间 | > 1000ms | WARNING | +| 错误率 | > 1% | WARNING | +| 错误率 | > 5% | CRITICAL | +| 数据库连接数 | > 80% | WARNING | +| OpenAI API 失败率 | > 10% | CRITICAL | + +## 11. 部署架构 + +### 11.1 开发环境 + +```mermaid +graph TB + DEV[开发环境] --> DEV_APP[单实例应用] + DEV_APP --> DEV_PG[(PostgreSQL)] + DEV_APP --> DEV_REDIS[(Redis)] + + style DEV_APP fill:#e1f5ff + style DEV_PG fill:#c8e6c9 +``` + +### 11.2 生产环境 + +```mermaid +graph TB + subgraph "生产环境" + LB[Load Balancer] + APP1[App Instance 1] + APP2[App Instance 2] + APP3[App Instance N] + PG_MASTER[(PostgreSQL Master)] + PG_SLAVE1[(PostgreSQL Slave 1)] + PG_SLAVE2[(PostgreSQL Slave 2)] + REDIS_CLUSTER[Redis Cluster] + MQ_CLUSTER[Message Queue Cluster] + end + + LB --> APP1 + LB --> APP2 + LB --> APP3 + + APP1 --> PG_MASTER + APP1 --> PG_SLAVE1 + APP1 --> REDIS_CLUSTER + APP1 --> MQ_CLUSTER + + APP2 --> PG_MASTER + APP2 --> PG_SLAVE2 + APP2 --> REDIS_CLUSTER + APP2 --> MQ_CLUSTER + + APP3 --> PG_MASTER + APP3 --> PG_SLAVE1 + APP3 --> REDIS_CLUSTER + APP3 --> MQ_CLUSTER + + PG_MASTER -.->|Replication| PG_SLAVE1 + PG_MASTER -.->|Replication| PG_SLAVE2 + + style LB fill:#e1f5ff + style PG_MASTER fill:#c8e6c9 + style REDIS_CLUSTER fill:#fff9c4 +``` + +### 11.3 部署策略 + +| 环境 | 实例数 | 数据库 | 缓存 | +|------|--------|--------|------| +| 开发 | 1 | 单实例 | 单实例 | +| 测试 | 2 | 1主1从 | 单实例 | +| 预发 | 2 | 1主2从 | 哨兵模式 | +| 生产 | 3+ | 1主N从 | 集群模式 | + +## 12. 总结 + +本架构设计遵循以下原则: + +1. **分层清晰**:表现层、应用层、服务层、领域层、基础设施层职责分明 +2. **高内聚低耦合**:各模块职责单一,依赖关系清晰 +3. **可扩展**:通过接口抽象支持多种扩展方式 +4. **高可用**:多实例部署、读写分离、故障降级 +5. **高性能**:多层缓存、异步处理、批量操作 +6. **安全可靠**:多层次安全防护、完善的监控告警 + +该架构能够满足 Agent+Skill 检索系统的核心需求,为后续实现提供清晰的指导。 diff --git a/docs/agent-skills-search/agent_teams/02-agent-module-design.md b/docs/agent-skills-search/agent_teams/02-agent-module-design.md new file mode 100644 index 00000000..82562f04 --- /dev/null +++ b/docs/agent-skills-search/agent_teams/02-agent-module-design.md @@ -0,0 +1,1472 @@ +# Agent 模块设计方案 + +## 1. 设计概述 + +本文档描述 Agent 对话上下文处理模块的设计方案,涵盖对话上下文管理、意图识别、元数据模型、pgvector 交互以及上下文向量化策略。 + +### 1.1 设计目标 + +- **上下文感知**:结合多轮对话历史,理解用户当前需求 +- **意图精准识别**:准确识别用户查询意图,提高技能匹配精度 +- **角色适配**:根据用户角色信息,推荐适合的技能 +- **场景理解**:基于场景描述,提供上下文相关的技能推荐 +- **高效检索**:利用 pgvector 进行高效的语义向量检索 + +### 1.2 核心模块 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Agent 模块架构 │ +│ ┌──────────────────┐ ┌──────────────────┐ ┌────────────────┐ │ +│ │ 上下文处理模块 │ │ 意图识别模块 │ │ 元数据管理模块 │ │ +│ │ Context Handler │ │ Intent Recognizer│ │ Metadata Mgr │ │ +│ └──────────────────┘ └──────────────────┘ └────────────────┘ │ +│ │ │ │ │ +│ └─────────────────────┴─────────────────────┘ │ +│ │ │ +│ ┌──────────────┐ │ +│ │ 向量化策略 │ │ +│ │ Vectorization│ │ +│ └──────┬───────┘ │ +│ │ │ +│ ┌──────────────┐ │ +│ │ pgvector │ │ +│ │ Interaction │ │ +│ └──────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 2. Agent 对话上下文处理模块 + +### 2.1 模块职责 + +- 收集和管理 Agent 与用户的对话历史 +- 构建完整的查询上下文 +- 维护会话状态和元数据 +- 提供上下文摘要和关键信息提取 + +### 2.2 核心组件 + +#### 2.2.1 ContextBuilder(上下文构建器) + +**职责**:将分散的信息整合成完整的搜索上下文 + +**输入参数**: +- `queryText`:当前用户查询文本 +- `sessionId`:会话标识符 +- `userId`:用户标识 +- `agentId`:Agent 标识 + +**输出**:`AgentSearchContext` 对象 + +**处理流程**: +1. 验证输入参数的有效性 +2. 根据 sessionId 获取会话信息 +3. 获取历史对话消息(最近 N 轮) +4. 提取场景描述和用户角色 +5. 整合元数据信息 +6. 构建返回上下文对象 + +#### 2.2.2 ConversationManager(对话管理器) + +**职责**:管理对话消息的存储和检索 + +**核心功能**: +- 保存新消息到会话 +- 获取会话历史消息 +- 对话轮次计数 +- 消息角色验证(user/assistant/system) +- 对话摘要生成 + +**存储策略**: +- 热数据:Redis 缓存,TTL 1 小时 +- 冷数据:PostgreSQL 持久化 +- 混合模式:优先从缓存读取,缓存未命中时查询数据库 + +#### 2.2.3 ContextSummarizer(上下文摘要器) + +**职责**:从多轮对话中提取关键信息 + +**摘要策略**: +- **轮次限制**:保留最近 N 轮对话(默认 5 轮) +- **关键信息提取**: + - 用户提到的技术栈关键词 + - 用户遇到的问题类型 + - 之前推荐的技能及反馈 +- **上下文压缩**:将长对话压缩为紧凑的摘要文本 + +**摘要格式**: +``` +[上下文摘要] +用户需求: {用户的核心需求} +技术栈: {识别出的技术关键词} +历史推荐: {之前推荐的技能及用户反馈} +当前状态: {对话当前进展状态} +``` + +### 2.3 上下文数据结构 + +#### AgentSearchContext + +``` +AgentSearchContext { + // 基础信息 + query: String // 当前查询文本 + sessionId: String // 会话 ID + userId: String // 用户 ID + agentId: String // Agent ID + + // 对话历史 + conversationHistory: List // 历史消息列表 + conversationSummary: String // 对话摘要 + turnCount: Integer // 对话轮次 + + // 场景和角色 + scenarioDescription: String // 场景描述 + userRole: String // 用户角色 + + // 意图信息 + detectedIntent: IntentInfo // 识别的意图 + intentConfidence: Float // 意图置信度 + + // 元数据 + metadata: Map // 扩展元数据 + userPreferences: Map // 用户偏好设置 + + // 时间信息 + contextTimestamp: Instant // 上下文构建时间 +} +``` + +#### AgentMessage + +``` +AgentMessage { + id: Long // 消息 ID + sessionId: Long // 所属会话 ID + role: MessageRole // 消息角色 (USER/ASSISTANT/SYSTEM) + content: String // 消息内容 + intentLabel: String? // 识别的意图标签 + intentConfidence: Float? // 意图置信度 + embedding: Vector? // 消息向量 + metadata: Map // 消息元数据 + createdAt: Instant // 创建时间 +} +``` + +### 2.4 上下文处理流程 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 1. 请求接收 │ +│ └─ 接收查询文本、sessionId、userId、agentId │ +└────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 2. 会话获取 │ +│ ├─ 尝试从 Redis 获取会话 │ +│ ├─ 缓存未命中时从 PostgreSQL 获取 │ +│ └─ 会话不存在时创建新会话 │ +└────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 3. 对话历史加载 │ +│ ├─ 获取最近 N 轮消息 │ +│ ├─ 过滤系统消息 │ +│ └─ 按时间排序 │ +└────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 4. 上下文摘要生成 │ +│ ├─ 提取关键关键词 │ +│ ├─ 识别用户意图变化 │ +│ └─ 生成紧凑摘要文本 │ +└────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 5. 场景和角色信息整合 │ +│ ├─ 从会话元数据中获取场景描述 │ +│ ├─ 获取用户角色信息 │ +│ └─ 加载用户偏好设置 │ +└────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 6. 上下文对象构建 │ +│ └─ 整合所有信息,返回 AgentSearchContext │ +└─────────────────────────────────────────────────────────────┘ +``` + +--- + +## 3. 意图识别模块 + +### 3.1 模块职责 + +- 识别用户查询的真实意图 +- 提供意图置信度评估 +- 支持多意图分类 +- 意图库动态管理 + +### 3.2 识别策略 + +#### 3.2.1 基于向量相似度的意图分类 + +**核心原理**:将用户查询向量化后,与预定义的意图嵌入向量计算余弦相似度 + +**实现步骤**: +1. 将用户查询文本转换为向量 +2. 从数据库加载所有活跃意图的嵌入向量 +3. 计算查询向量与每个意图向量的余弦相似度 +4. 按相似度降序排序 +5. 返回 Top-N 意图及置信度 + +**相似度计算公式**: +``` +similarity(query, intent) = cosine_similarity( + embed(query_text), + intent.embedding_vector +) +``` + +**置信度映射**: +- 相似度 >= 0.8:高置信度 (0.8-1.0) +- 相似度 >= 0.5:中等置信度 (0.5-0.8) +- 相似度 >= 0.3:低置信度 (0.3-0.5) +- 相似度 < 0.3:返回默认意图 "general" + +#### 3.2.2 多意图支持 + +**场景**:用户查询可能涉及多个意图 + +**处理策略**: +- 返回 Top-3 候选意图 +- 主意图:相似度最高的意图 +- 备选意图:相似度次高的意图 +- 意图组合:当多个意图相似度接近时,标记为组合意图 + +**组合意图示例**: +- 查询:"生成一个处理用户数据的 API" +- 识别结果: + - 主意图:code_generation (0.85) + - 备选意图:api_integration (0.78) + - 组合标记:code_generation + api_integration + +### 3.3 意图库设计 + +#### 3.3.1 预定义意图类别 + +| 意图标签 | 描述 | 示例查询 | 关联技能类别 | +|----------|------|----------|--------------| +| code_generation | 代码生成 | "写一个函数"、"生成代码" | coding, development | +| data_analysis | 数据分析 | "分析数据"、"绘制图表" | data, analysis, visualization | +| text_processing | 文本处理 | "处理文本"、"提取关键词" | text, nlp, language | +| api_integration | API 集成 | "调用 API"、"HTTP 请求" | api, integration, web | +| file_processing | 文件处理 | "读取文件"、"写入文件" | file, io, storage | +| database | 数据库操作 | "查询数据库"、"SQL 语句" | database, sql, storage | +| general | 通用查询 | "帮助"、"能做什么" | general | + +#### 3.3.2 意图嵌入向量生成 + +**生成策略**: +1. 收集每个意图的示例查询(至少 5 条) +2. 将所有示例查询转换为向量 +3. 计算示例向量的平均值作为意图的嵌入向量 +4. 存储到 intent_mapping 表 + +**更新策略**: +- 定期更新:基于用户查询数据重新计算意图向量 +- 手动更新:管理员通过管理界面添加/修改意图示例 +- 增量更新:新示例查询时,更新意图向量的移动平均值 + +### 3.4 意图识别流程 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 1. 接收查询文本 │ +└────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 2. 文本预处理 │ +│ ├─ 去除特殊字符 │ +│ ├─ 分词和标准化 │ +│ └─ 停用词过滤 │ +└────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 3. 查询向量化 │ +│ ├─ 调用 OpenAI Embedding API │ +│ ├─ 或使用缓存的查询向量 │ +│ └─ 获取 1536 维向量 │ +└────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 4. 意图向量加载 │ +│ ├─ 从 Redis 缓存加载意图向量 │ +│ ├─ 或从 PostgreSQL 查询 │ +│ └─ 过滤活跃的意图 │ +└────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 5. 相似度计算 │ +│ ├─ 计算查询向量与每个意图向量的余弦相似度 │ +│ ├─ pgvector 使用 <=> 操作符 │ +│ └─ 得到每个意图的相似度分数 │ +└────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 6. 结果排序和筛选 │ +│ ├─ 按相似度降序排序 │ +│ ├─ 检查最高相似度是否超过阈值 │ +│ └─ 阈值以下返回 "general" 意图 │ +└────────────────┬────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ 7. 返回识别结果 │ +│ ├─ 主意图及置信度 │ +│ ├─ 备选意图列表 │ +│ └─ 处理时间统计 │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 3.5 意图识别数据结构 + +#### IntentInfo + +``` +IntentInfo { + id: Long // 意图 ID + label: String // 意图标签 + description: String // 意图描述 + skillCategories: List // 关联的技能类别 + exampleQueries: List // 示例查询 + embedding: Vector // 意图嵌入向量 + priority: Integer // 优先级 + active: Boolean // 是否活跃 + createdAt: Instant // 创建时间 + updatedAt: Instant // 更新时间 +} +``` + +#### IntentClassificationResult + +``` +IntentClassificationResult { + primaryIntent: IntentMatch // 主意图 + alternativeIntents: List // 备选意图 + isMixed: Boolean // 是否为混合意图 + processingTimeMs: Long // 处理时间(毫秒) + confidenceThreshold: Float // 使用的置信度阈值 +} + +IntentMatch { + intentLabel: String // 意图标签 + confidence: Float // 置信度 + similarity: Float // 相似度分数 + matchedCategories: List // 匹配的技能类别 +} +``` + +--- + +## 4. Agent 元数据模型 + +### 4.1 元数据架构 + +Agent 元数据采用分层结构设计,支持灵活的扩展和高效的查询。 + +``` +Agent Metadata Hierarchy +├── Agent 基础信息 +│ ├── Agent ID +│ ├── Agent 名称 +│ ├── Agent 类型 +│ └── Agent 状态 +├── 用户信息 +│ ├── 用户 ID +│ ├── 用户角色 +│ ├── 用户权限 +│ └── 用户偏好 +├── 会话信息 +│ ├── 会话 ID +│ ├── 场景描述 +│ ├── 会话状态 +│ └── 会话元数据 +├── 标签系统 +│ ├── 用户标签 +│ ├── 场景标签 +│ ├── 技能标签 +│ └── 自定义标签 +└── 扩展元数据 + ├── 键值对存储 + ├── 嵌套对象 + └── 数组类型 +``` + +### 4.2 用户角色模型 + +#### 4.2.1 角色定义 + +| 角色代码 | 角色名称 | 描述 | 权限级别 | +|----------|----------|------|----------| +| admin | 管理员 | 系统管理员,拥有所有权限 | FULL | +| developer | 开发者 | 软件开发者,可以使用开发相关技能 | HIGH | +| data_analyst | 数据分析师 | 数据分析人员,使用数据处理技能 | HIGH | +| designer | 设计师 | UI/UX 设计师,使用设计相关技能 | MEDIUM | +| tester | 测试人员 | QA 工程师,使用测试相关技能 | MEDIUM | +| user | 普通用户 | 普通用户,使用基础技能 | LOW | +| guest | 访客 | 未登录用户,受限访问 | MINIMAL | + +#### 4.2.2 角色数据结构 + +``` +UserRole { + id: String // 角色 ID + code: String // 角色代码 + name: String // 角色名称 + description: String // 角色描述 + permissions: List // 权限列表 + skillCategories: List // 可访问的技能类别 + metadata: Map // 角色元数据 + createdAt: Instant // 创建时间 + updatedAt: Instant // 更新时间 +} + +Permission { + resource: String // 资源类型 + action: String // 操作类型 + conditions: Map // 条件限制 +} +``` + +### 4.3 标签系统模型 + +#### 4.3.1 标签类型 + +| 标签类型 | 说明 | 示例 | +|----------|------|------| +| 技术栈标签 | 表示使用的技术 | "python", "react", "postgresql" | +| 功能标签 | 表示技能的功能 | "file-io", "data-processing", "api-call" | +| 场景标签 | 表示使用场景 | "web-development", "data-science", "automation" | +| 难度标签 | 表示使用难度 | "beginner", "intermediate", "advanced" | +| 状态标签 | 表示技能状态 | "stable", "experimental", "deprecated" | +| 自定义标签 | 用户自定义标签 | "my-favorite", "team-internal" | + +#### 4.3.2 标签数据结构 + +``` +TagDefinition { + id: Long // 标签 ID + slug: String // 标签标识符(URL 友好) + name: String // 标签名称 + type: TagType // 标签类型 + description: String // 标签描述 + color: String? // 标签颜色(用于 UI 显示) + icon: String? // 标签图标 + metadata: Map // 标签元数据 + createdAt: Instant // 创建时间 + updatedAt: Instant // 更新时间 +} + +TagType { + TECH_STACK // 技术栈 + FUNCTION // 功能 + SCENARIO // 场景 + DIFFICULTY // 难度 + STATUS // 状态 + CUSTOM // 自定义 +} +``` + +### 4.4 场景描述模型 + +#### 4.4.1 预定义场景 + +| 场景代码 | 场景名称 | 描述 | 关联技能类别 | +|----------|----------|------|--------------| +| web_frontend | Web 前端开发 | 前端页面和交互开发 | frontend, javascript, css | +| web_backend | Web 后端开发 | 服务器端 API 开发 | backend, api, database | +| data_science | 数据科学 | 数据分析和机器学习 | data, analysis, ml | +| mobile_dev | 移动应用开发 | 移动端 App 开发 | mobile, ios, android | +| devops | DevOps | 运维和部署 | deployment, ci-cd, infrastructure | +| automation | 自动化 | 自动化脚本和流程 | automation, scripting, scheduling | +| testing | 软件测试 | 测试和质量保证 | testing, qa, quality | + +#### 4.4.2 场景数据结构 + +``` +Scenario { + id: String // 场景 ID + code: String // 场景代码 + name: String // 场景名称 + description: String // 场景描述 + skillCategories: List // 推荐的技能类别 + defaultTags: List // 默认标签 + suggestedSkills: List // 推荐技能 ID 列表 + metadata: Map // 场景元数据 + createdAt: Instant // 创建时间 + updatedAt: Instant // 更新时间 +} +``` + +### 4.5 元数据存储策略 + +#### 4.5.1 存储位置 + +| 数据类型 | 存储位置 | 访问频率 | 更新频率 | +|----------|----------|----------|----------| +| Agent 基础信息 | PostgreSQL | 高 | 低 | +| 用户角色信息 | PostgreSQL + Redis | 高 | 低 | +| 会话信息 | PostgreSQL + Redis | 高 | 高 | +| 标签定义 | PostgreSQL + Redis | 高 | 低 | +| 场景定义 | PostgreSQL + Redis | 中 | 低 | +| 用户偏好 | PostgreSQL | 中 | 中 | +| 自定义元数据 | PostgreSQL (JSONB) | 中 | 高 | + +#### 4.5.2 缓存策略 + +- **热点数据**:频繁访问的元数据缓存到 Redis +- **缓存键设计**: + - 用户角色:`agent:role:{userId}` + - 标签定义:`agent:tag:{tagSlug}` + - 场景定义:`agent:scenario:{scenarioCode}` + - 用户偏好:`agent:preferences:{userId}` +- **缓存过期**: + - 基础元数据:24 小时 + - 用户偏好:1 小时 + - 会话信息:10 分钟 + +### 4.6 元数据查询接口 + +``` +// 获取用户角色 +getUserRole(userId: String): UserRole + +// 获取用户标签 +getUserTags(userId: String): List + +// 获取场景信息 +getScenario(scenarioCode: String): Scenario + +// 获取用户偏好 +getUserPreferences(userId: String): Map + +// 搜索标签 +searchTags(query: String, type: TagType?): List + +// 根据角色获取可访问的技能类别 +getAccessibleCategories(roleCode: String): List + +// 根据场景获取推荐技能 +getRecommendedSkills(scenarioCode: String): List +``` + +--- + +## 5. 与 pgvector 交互的数据结构 + +### 5.1 向量存储设计 + +#### 5.1.1 向量表结构 + +使用现有的 skill_embedding 表进行向量存储,支持多种嵌入类型: + +```sql +skill_embedding ( + id BIGSERIAL PRIMARY KEY, + skill_id BIGINT NOT NULL, + skill_version_id BIGINT, + embedding_type VARCHAR(32) NOT NULL, -- description/example/usage/combined + embedding vector(1536) NOT NULL, + metadata JSONB DEFAULT '{}', + updated_at TIMESTAMP WITH TIME ZONE NOT NULL +) +``` + +#### 5.1.2 向量索引策略 + +使用 ivfflat 索引类型,平衡精度和性能: + +```sql +CREATE INDEX idx_skill_embedding_embedding +ON skill_embedding +USING ivfflat(embedding vector_cosine_ops) +WITH (lists = 100); +``` + +**索引参数调优**: +- lists = sqrt(行数) +- 1000 行:lists = 32 +- 10000 行:lists = 100 +- 100000 行:lists = 316 + +### 5.2 查询向量构建 + +#### 5.2.1 多维度向量融合 + +将多种上下文信息融合为一个查询向量: + +``` +query_vector = normalize( + w1 * embed(query_text) + + w2 * embed(conversation_summary) + + w3 * embed(scenario_description) + + w4 * embed(user_role) + + w5 * intent_embedding +) +``` + +**权重配置**: + +| 权重 | 值 | 说明 | +|------|-----|------| +| w1 | 0.4 | 查询文本(最重要) | +| w2 | 0.2 | 对话上下文摘要 | +| w3 | 0.15 | 场景描述 | +| w4 | 0.1 | 用户角色 | +| w5 | 0.15 | 意图向量 | + +#### 5.2.2 向量归一化 + +确保所有向量在同一尺度上: + +``` +normalize(vector): + norm = sqrt(sum(v[i]² for i in range(len(vector)))) + if norm == 0: + return vector + return vector / norm +``` + +### 5.3 pgvector 查询接口 + +#### 5.3.1 向量相似度查询 + +```sql +-- 基础相似度查询 +SELECT + se.skill_id, + s.name, + s.summary, + 1 - (se.embedding <=> :query_vector) as similarity +FROM skill_embedding se +JOIN skill s ON s.id = se.skill_id +WHERE se.embedding_type = 'description' + AND s.status = 'ACTIVE' +ORDER BY se.embedding <=> :query_vector +LIMIT :limit; +``` + +#### 5.3.2 多类型向量融合查询 + +```sql +-- 融合多种嵌入类型的查询 +WITH description_scores AS ( + SELECT + skill_id, + 1 - (embedding <=> :query_vector) as score + FROM skill_embedding + WHERE embedding_type = 'description' +), +combined_scores AS ( + SELECT + skill_id, + 1 - (embedding <=> :query_vector) as score + FROM skill_embedding + WHERE embedding_type = 'combined' +), +fused_scores AS ( + SELECT + COALESCE(d.skill_id, c.skill_id) as skill_id, + (COALESCE(d.score, 0) * 0.6 + COALESCE(c.score, 0) * 0.4) as fused_score + FROM description_scores d + FULL OUTER JOIN combined_scores c ON d.skill_id = c.skill_id +) +SELECT + fs.skill_id, + s.name, + s.summary, + fs.fused_score as similarity +FROM fused_scores fs +JOIN skill s ON s.id = fs.skill_id +WHERE s.status = 'ACTIVE' +ORDER BY fs.fused_score DESC +LIMIT :limit; +``` + +#### 5.3.3 带过滤条件的向量查询 + +```sql +-- 结合意图、标签、权限过滤的向量查询 +WITH vector_candidates AS ( + SELECT + se.skill_id, + 1 - (se.embedding <=> :query_vector) as vector_score + FROM skill_embedding se + JOIN skill s ON s.id = se.skill_id + WHERE se.embedding_type = 'description' + AND s.status = 'ACTIVE' + AND s.category = ANY(:intent_categories) + ORDER BY se.embedding <=> :query_vector + LIMIT 200 +), +tag_filtered AS ( + SELECT + vc.skill_id, + vc.vector_score, + COUNT(DISTINCT ld.slug) FILTER ( + WHERE ld.slug = ANY(:user_tags) + ) as tag_match_count + FROM vector_candidates vc + LEFT JOIN skill_label sl ON sl.skill_id = vc.skill_id + LEFT JOIN label_definition ld ON ld.id = sl.label_id + GROUP BY vc.skill_id, vc.vector_score +) +SELECT + tf.skill_id, + s.name, + s.summary, + tf.vector_score, + tf.tag_match_count, + s.download_count, + s.rating_avg +FROM tag_filtered tf +JOIN skill s ON s.id = tf.skill_id +WHERE (s.visibility = 'PUBLIC') + OR (s.visibility = 'NAMESPACE_ONLY' AND s.namespace_id = ANY(:member_namespace_ids)) + OR (s.visibility = 'PRIVATE' AND (s.owner_id = :user_id)) +ORDER BY tf.vector_score DESC +LIMIT :limit; +``` + +### 5.4 向量操作封装 + +#### 5.4.1 向量插入 + +```sql +-- 插入技能向量 +INSERT INTO skill_embedding ( + skill_id, + skill_version_id, + embedding_type, + embedding, + metadata +) VALUES ( + :skill_id, + :skill_version_id, + :embedding_type, + :embedding_vector, + :metadata::jsonb +) +ON CONFLICT (skill_id, embedding_type) +DO UPDATE SET + embedding = EXCLUDED.embedding, + updated_at = NOW(); +``` + +#### 5.4.2 批量向量插入 + +```sql +-- 批量插入技能向量 +INSERT INTO skill_embedding ( + skill_id, + embedding_type, + embedding, + metadata +) +SELECT + unnest(:skill_ids)::BIGINT, + unnest(:embedding_types), + unnest(:embeddings)::vector(1536), + unnest(:metadata_array)::jsonb +ON CONFLICT (skill_id, embedding_type) +DO UPDATE SET + embedding = EXCLUDED.embedding, + updated_at = NOW(); +``` + +#### 5.4.3 向量删除 + +```sql +-- 删除技能向量 +DELETE FROM skill_embedding +WHERE skill_id = :skill_id; + +-- 删除特定类型的向量 +DELETE FROM skill_embedding +WHERE skill_id = :skill_id + AND embedding_type = :embedding_type; +``` + +### 5.5 向量缓存策略 + +#### 5.5.1 缓存设计 + +| 缓存类型 | 缓存键 | TTL | 更新策略 | +|----------|--------|-----|----------| +| 技能向量 | `skill:embedding:{skill_id}:{type}` | 永久 | 技能更新时失效 | +| 意图向量 | `intent:embedding:{intent_label}` | 永久 | 意图更新时失效 | +| 查询向量 | `query:embedding:{hash(query_text)}` | 1 小时 | 主动过期 | +| 向量索引状态 | `vector:index:status` | 5 分钟 | 定期刷新 | + +#### 5.5.2 缓存实现 + +``` +// 获取技能向量 +getSkillEmbedding(skillId: Long, type: EmbeddingType): Vector + +// 缓存技能向量 +cacheSkillEmbedding(skillId: Long, type: EmbeddingType, vector: Vector) + +// 批量预加载技能向量 +preloadSkillEmbeddings(skillIds: List, type: EmbeddingType) + +// 失效技能向量缓存 +invalidateSkillEmbedding(skillId: Long) + +// 失效所有向量缓存 +invalidateAllEmbeddings() +``` + +--- + +## 6. Agent 上下文向量化策略 + +### 6.1 向量化策略概述 + +Agent 上下文向量化是将多维上下文信息转换为统一向量表示的过程,是实现语义相似度检索的关键。 + +### 6.2 分层向量化策略 + +#### 6.2.1 第一层:基础文本向量化 + +**对象**:查询文本本身 + +**方法**:直接调用 OpenAI Embedding API + +**输入**:用户原始查询文本 + +**输出**:1536 维向量 + +**权重**:0.4 + +#### 6.2.2 第二层:对话上下文向量化 + +**对象**:对话历史摘要 + +**方法**: +1. 提取最近 N 轮对话 +2. 生成对话摘要(见第 2.2.3 节) +3. 对摘要文本进行向量化 + +**输入**:对话摘要文本 + +**输出**:1536 维向量 + +**权重**:0.2 + +#### 6.2.3 第三层:场景描述向量化 + +**对象**:使用场景 + +**方法**: +1. 获取场景描述文本 +2. 结合场景代码和名称构建增强描述 +3. 对增强描述进行向量化 + +**输入**:场景代码 + 场景名称 + 场景描述 + +**输出**:1536 维向量 + +**权重**:0.15 + +#### 6.2.4 第四层:用户角色向量化 + +**对象**:用户角色和权限 + +**方法**: +1. 获取用户角色名称和描述 +2. 获取角色关联的技能类别 +3. 构建角色特征文本 +4. 对角色特征文本进行向量化 + +**输入**:角色名称 + 角色描述 + 关联技能类别 + +**输出**:1536 维向量 + +**权重**:0.1 + +#### 6.2.5 第五层:意图向量化 + +**对象**:识别出的意图 + +**方法**: +1. 执行意图识别 +2. 获取意图的预定义嵌入向量 +3. 直接使用意图向量(无需重新计算) + +**输入**:意图标签 + +**输出**:1536 维向量(来自预定义意图库) + +**权重**:0.15 + +### 6.3 向量融合算法 + +#### 6.3.1 加权平均融合 + +``` +def fuse_vectors(vectors: List[Vector], weights: List[float]) -> Vector: + """ + 使用加权平均融合多个向量 + + Args: + vectors: 待融合的向量列表 + weights: 对应的权重列表 + + Returns: + 融合后的向量 + """ + # 确保向量维度一致 + dimension = len(vectors[0]) + fused = [0.0] * dimension + + # 加权求和 + for vec, weight in zip(vectors, weights): + for i in range(dimension): + fused[i] += vec[i] * weight + + # 归一化 + norm = math.sqrt(sum(x * x for x in fused)) + if norm > 0: + fused = [x / norm for x in fused] + + return fused +``` + +#### 6.3.2 自适应权重调整 + +根据上下文信息动态调整权重: + +``` +def adaptive_weights(context: AgentSearchContext) -> List[float]: + """ + 根据上下文自适应调整权重 + + Args: + context: Agent 搜索上下文 + + Returns: + 调整后的权重列表 + """ + base_weights = [0.4, 0.2, 0.15, 0.1, 0.15] # 基础权重 + + # 对话轮次多时,增加对话上下文权重 + if context.turnCount > 5: + base_weights[1] = min(base_weights[1] + 0.1, 0.4) + base_weights[0] -= 0.1 + + # 意图置信度高时,增加意图权重 + if context.intentConfidence > 0.8: + base_weights[4] = min(base_weights[4] + 0.05, 0.2) + base_weights[2] -= 0.05 + + # 场景描述明确时,增加场景权重 + if context.scenarioDescription and len(context.scenarioDescription) > 50: + base_weights[2] = min(base_weights[2] + 0.05, 0.2) + base_weights[3] -= 0.05 + + # 确保权重总和为 1 + total = sum(base_weights) + base_weights = [w / total for w in base_weights] + + return base_weights +``` + +### 6.4 向量化优化策略 + +#### 6.4.1 向量缓存 + +**缓存键设计**: +``` +vector_cache:{hash(content)}:{model_version} +``` + +**缓存策略**: +- 技能向量:永久缓存 +- 意图向量:永久缓存 +- 查询向量:TTL 1 小时 +- 对话摘要向量:TTL 10 分钟 + +#### 6.4.2 批量向量化 + +对于多个文本的向量化,使用批量 API 减少调用次数: + +``` +def batch_embed(texts: List[str], batch_size: int = 100) -> List[Vector]: + """ + 批量生成嵌入向量 + + Args: + texts: 文本列表 + batch_size: 每批处理的文本数量 + + Returns: + 向量列表 + """ + all_embeddings = [] + for i in range(0, len(texts), batch_size): + batch = texts[i:i + batch_size] + # 调用批量 Embedding API + response = openai.Embedding.create( + model="text-embedding-3-small", + input=batch + ) + batch_embeddings = [item['embedding'] for item in response['data']] + all_embeddings.extend(batch_embeddings) + return all_embeddings +``` + +#### 6.4.3 异步向量化 + +对于非实时要求的向量化任务,使用异步处理: + +``` +async def async_embed(text: str) -> Vector: + """ + 异步生成嵌入向量 + + Args: + text: 待向量化的文本 + + Returns: + 向量 + """ + # 使用异步 HTTP 客户端调用 API + async with httpx.AsyncClient() as client: + response = await client.post( + "https://api.openai.com/v1/embeddings", + json={ + "model": "text-embedding-3-small", + "input": text + }, + headers={"Authorization": f"Bearer {API_KEY}"} + ) + data = response.json() + return data['data'][0]['embedding'] +``` + +### 6.5 向量质量控制 + +#### 6.5.1 向量维度验证 + +``` +def validate_vector(vector: Vector, expected_dim: int = 1536) -> bool: + """ + 验证向量维度 + + Args: + vector: 待验证的向量 + expected_dim: 期望的维度 + + Returns: + 是否有效 + """ + if len(vector) != expected_dim: + return False + if not all(isinstance(x, (int, float)) for x in vector): + return False + if any(math.isnan(x) or math.isinf(x) for x in vector): + return False + return True +``` + +#### 6.5.2 向量归一化检查 + +``` +def is_normalized(vector: Vector, tolerance: float = 1e-6) -> bool: + """ + 检查向量是否已归一化 + + Args: + vector: 待检查的向量 + tolerance: 容差范围 + + Returns: + 是否已归一化 + """ + norm = math.sqrt(sum(x * x for x in vector)) + return abs(norm - 1.0) < tolerance +``` + +### 6.6 向量降级策略 + +当 OpenAI API 调用失败时,使用降级策略: + +#### 6.6.1 本地哈希向量 + +``` +def fallback_hash_vector(text: str, dim: int = 1536) -> Vector: + """ + 使用哈希算法生成降级向量 + + Args: + text: 输入文本 + dim: 向量维度 + + Returns: + 降级向量 + """ + # 使用 SHA256 哈希 + hash_obj = hashlib.sha256(text.encode('utf-8')) + hash_bytes = hash_obj.digest() + + # 扩展到指定维度 + vector = [] + for i in range(dim): + byte = hash_bytes[i % len(hash_bytes)] + # 将字节映射到 [-1, 1] 范围 + value = (byte / 127.5) - 1.0 + vector.append(value) + + # 归一化 + norm = math.sqrt(sum(x * x for x in vector)) + if norm > 0: + vector = [x / norm for x in vector] + + return vector +``` + +#### 6.6.2 缓存向量复用 + +``` +def get_cached_or_fallback_vector( + text: str, + cache_key: str, + fallback_func: Callable +) -> Vector: + """ + 获取缓存向量或使用降级策略 + + Args: + text: 输入文本 + cache_key: 缓存键 + fallback_func: 降级函数 + + Returns: + 向量 + """ + # 尝试从缓存获取 + cached = cache.get(cache_key) + if cached and validate_vector(cached): + return cached + + # 尝试调用 API + try: + vector = call_embedding_api(text) + cache.set(cache_key, vector, ttl=3600) + return vector + except Exception as e: + logger.warning(f"Embedding API failed: {e}, using fallback") + # 使用降级策略 + vector = fallback_func(text) + cache.set(cache_key, vector, ttl=300) # 降级向量缓存时间短 + return vector +``` + +--- + +## 7. 模块交互流程 + +### 7.1 完整处理流程 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Agent 请求处理流程 │ +└─────────────────────────────────────────────────────────────────┘ + +┌─────────────────────────────────────────────────────────────────┐ +│ 1. 请求接收层 │ +│ └─ 接收 Agent 发送的搜索请求 │ +│ ├─ query: 查询文本 │ +│ ├─ sessionId: 会话 ID │ +│ ├─ userId: 用户 ID │ +│ └─ options: 可选参数(标签、意图等) │ +└────────────────┬────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ 2. 上下文处理模块 │ +│ ├─ ContextBuilder: 构建搜索上下文 │ +│ │ ├─ 获取会话信息 │ +│ │ ├─ 加载对话历史 │ +│ │ ├─ 生成对话摘要 │ +│ │ ├─ 提取场景和角色信息 │ +│ │ └─ 构建 AgentSearchContext │ +│ │ │ +│ └─ ConversationManager: 管理对话 │ +│ ├─ 保存当前消息 │ +│ └─ 更新会话状态 │ +└────────────────┬────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ 3. 意图识别模块 │ +│ └─ IntentRecognizer: 识别查询意图 │ +│ ├─ 文本预处理 │ +│ ├─ 查询向量化 │ +│ ├─ 加载意图向量 │ +│ ├─ 计算相似度 │ +│ └─ 返回 IntentClassificationResult │ +└────────────────┬────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ 4. 元数据管理模块 │ +│ └─ MetadataManager: 获取元数据 │ +│ ├─ 获取用户角色和权限 │ +│ ├─ 获取用户标签 │ +│ ├─ 获取场景信息 │ +│ └─ 获取用户偏好 │ +└────────────────┬────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ 5. 向量化策略模块 │ +│ └─ VectorizationStrategy: 生成查询向量 │ +│ ├─ 查询文本向量化 (w1=0.4) │ +│ ├─ 对话上下文向量化 (w2=0.2) │ +│ ├─ 场景描述向量化 (w3=0.15) │ +│ ├─ 用户角色向量化 (w4=0.1) │ +│ ├─ 意图向量化 (w5=0.15) │ +│ ├─ 自适应权重调整 │ +│ └─ 向量融合和归一化 │ +└────────────────┬────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ 6. pgvector 交互模块 │ +│ └─ VectorSearchService: 执行向量检索 │ +│ ├─ 构建向量查询 SQL │ +│ ├─ 执行 pgvector 相似度查询 │ +│ ├─ 应用意图、标签、权限过滤 │ +│ └─ 返回候选技能列表 │ +└────────────────┬────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ 7. 重排序模块 │ +│ └─ SkillReranker: 多维度评分和排序 │ +│ ├─ 计算意图匹配分数 │ +│ ├─ 计算标签匹配分数 │ +│ ├─ 计算流行度分数 │ +│ ├─ 计算用户评分分数 │ +│ ├─ 综合评分计算 │ +│ └─ 生成匹配原因说明 │ +└────────────────┬────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ 8. 响应构建 │ +│ └─ 构建统一的响应格式 │ +│ ├─ 包含查询信息 │ +│ ├─ 包含意图识别结果 │ +│ ├─ 包含技能列表和评分 │ +│ └─ 包含处理时间统计 │ +└────────────────┬────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ 9. 返回响应 │ +│ └─ 返回给 Agent │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 7.2 模块依赖关系 + +``` +AgentSearchController + │ + ├─► ContextBuilder (上下文处理模块) + │ ├─► ConversationManager + │ │ └─► AgentSessionRepository + │ │ └─► PostgreSQL / Redis + │ │ + │ └─► ContextSummarizer + │ └─► LLM Service (可选) + │ + ├─► IntentRecognizer (意图识别模块) + │ ├─► EmbeddingService + │ │ └─► OpenAI API + │ │ + │ └─► IntentMappingRepository + │ └─► PostgreSQL + │ + ├─► MetadataManager (元数据管理模块) + │ ├─► UserRepository + │ ├─► RoleRepository + │ ├─► TagRepository + │ └─► ScenarioRepository + │ + ├─► VectorizationStrategy (向量化策略模块) + │ ├─► EmbeddingService + │ ├─► CacheService + │ └─► FallbackStrategy + │ + ├─► VectorSearchService (pgvector 交互模块) + │ ├─► SkillEmbeddingRepository + │ │ └─► PostgreSQL + pgvector + │ │ + │ └─► CacheService + │ └─► Redis + │ + └─► SkillReranker (重排序模块) + ├─► SkillRepository + └─► LabelRepository +``` + +--- + +## 8. 性能优化建议 + +### 8.1 缓存优化 + +1. **多级缓存**: + - L1:内存缓存(本地应用) + - L2:Redis 缓存(分布式) + - L3:数据库(持久化) + +2. **缓存预热**: + - 系统启动时预加载热点数据 + - 定期刷新即将过期的缓存 + +3. **缓存击穿防护**: + - 使用互斥锁防止并发重建 + - 设置合理的缓存过期时间 + +### 8.2 数据库优化 + +1. **索引优化**: + - 确保向量索引参数合理 + - 定期重建索引以保持性能 + +2. **查询优化**: + - 使用 CTE(Common Table Expressions)优化复杂查询 + - 限制返回的候选集大小 + - 使用批处理减少数据库往返 + +3. **连接池配置**: + - 合理设置连接池大小 + - 监控连接使用情况 + +### 8.3 API 调用优化 + +1. **批量处理**: + - 批量生成嵌入向量 + - 减少网络往返次数 + +2. **异步处理**: + - 非关键路径使用异步调用 + - 使用消息队列处理耗时任务 + +3. **降级策略**: + - API 失败时使用缓存或降级方案 + - 设置合理的超时时间 + +### 8.4 监控和告警 + +1. **性能指标**: + - 查询响应时间 + - 向量检索准确率 + - 意图识别准确率 + - 缓存命中率 + +2. **告警规则**: + - 响应时间超过阈值 + - 缓存命中率低于阈值 + - API 调用失败率超过阈值 + +--- + +## 9. 扩展性设计 + +### 9.1 插件化架构 + +支持通过插件扩展功能: + +- **意图识别插件**:支持不同的意图识别算法 +- **向量化插件**:支持不同的嵌入模型 +- **过滤插件**:支持自定义过滤规则 +- **评分插件**:支持自定义评分策略 + +### 9.2 配置化设计 + +关键参数支持动态配置: + +- 向量融合权重 +- 意图识别阈值 +- 缓存策略 +- 降级策略 + +### 9.3 多语言支持 + +- 支持多种语言的文本处理 +- 支持多语言意图识别 +- 支持多语言向量嵌入 + +--- + +## 10. 安全性考虑 + +### 10.1 权限控制 + +- 基于角色的访问控制(RBAC) +- 细粒度的技能可见性控制 +- 用户数据隔离 + +### 10.2 数据保护 + +- 敏感信息脱敏 +- 加密存储用户数据 +- 安全的 API 调用 + +### 10.3 防护措施 + +- 请求速率限制 +- 输入验证和清理 +- SQL 注入防护 +- XSS 防护 + +--- + +## 11. 总结 + +本设计方案提供了完整的 Agent 对话上下文处理模块架构,包括: + +1. **上下文处理模块**:负责收集和管理对话历史,构建完整的搜索上下文 +2. **意图识别模块**:基于向量相似度的意图分类,支持多意图识别 +3. **元数据模型**:分层设计的用户角色、标签、场景等元数据结构 +4. **pgvector 交互**:高效的向量存储和查询接口设计 +5. **向量化策略**:多维度向量融合和自适应权重调整 + +该设计方案具有以下特点: + +- **灵活性**:支持多种配置和扩展 +- **高性能**:多级缓存和优化策略 +- **可靠性**:降级策略和错误处理 +- **可维护性**:清晰的模块划分和接口定义 +- **可扩展性**:插件化架构和配置化设计 + +通过该设计方案,系统能够准确理解用户意图,结合多轮对话上下文,为 Agent 推荐最合适的技能。 diff --git a/docs/agent-skills-search/agent_teams/03-skills-module-design.md b/docs/agent-skills-search/agent_teams/03-skills-module-design.md new file mode 100644 index 00000000..796c981a --- /dev/null +++ b/docs/agent-skills-search/agent_teams/03-skills-module-design.md @@ -0,0 +1,321 @@ +# Skills 模块设计方案 + +## 1. Skill 数据模型设计 + +### 1.1 核心数据表结构 + +#### skills 表 +| 字段名 | 类型 | 说明 | 索引 | +|--------|------|------|------| +| id | uuid | 主键 | PK | +| name | varchar(255) | Skill 名称 | | +| description | text | Skill 描述 | | +| embedding | vector(1536) | 语义向量(基于 description 生成) | pgvector | +| category_id | uuid | 所属分类 | FK | +| is_active | boolean | 是否启用 | | +| created_at | timestamp | 创建时间 | | +| updated_at | timestamp | 更新时间 | | + +#### skill_tags 表 +| 字段名 | 类型 | 说明 | 索引 | +|--------|------|------|------| +| id | uuid | 主键 | PK | +| skill_id | uuid | 关联的 skill | FK | +| tag | varchar(100) | 标签名称 | | +| tag_type | varchar(50) | 标签类型(domain/role/action) | | + +#### skill_metadata 表 +| 字段名 | 类型 | 说明 | 索引 | +|--------|------|------|------| +| id | uuid | 主键 | PK | +| skill_id | uuid | 关联的 skill | FK | +| key | varchar(100) | 元数据键 | | +| value | text | 元数据值(JSON 格式) | | + +#### skill_categories 表 +| 字段名 | 类型 | 说明 | 索引 | +|--------|------|------|------| +| id | uuid | 主键 | PK | +| name | varchar(100) | 分类名称 | | +| parent_id | uuid | 父分类 | FK | +| level | int | 分类层级 | | + +### 1.2 向量化方案 + +#### 向量化内容来源 +1. **主要向量**:基于 Skill 的 `description` 字段 +2. **增强向量**:合并 `name` + `description` + `tags` 生成更丰富的语义表示 +3. **多维度向量**:针对不同场景生成独立向量(如:技术栈向量、业务场景向量) + +#### 向量维度选择 +- 推荐维度:1536(OpenAI text-embedding-3-small/large) +- 备选维度:768(轻量级场景) +- 存储类型:`vector(1536)` 或 `vector(768)` + +#### 向量更新策略 +- 创建 Skill 时自动生成向量 +- 当 `description`、`name`、`tags` 变更时,异步重新计算向量 +- 支持手动触发向量重新生成 + +## 2. Skill 标签和元数据结构 + +### 2.1 标签分类体系 + +#### Domain 标签(领域标签) +- 描述 Skill 所属业务领域 +- 示例:`database`、`api`、`auth`、`ui`、`testing`、`deployment` + +#### Role 标签(角色标签) +- 描述适合使用该 Skill 的角色 +- 示例:`developer`、`devops`、`analyst`、`designer`、`manager` + +#### Action 标签(动作标签) +- 描述 Skill 的主要动作类型 +- 示例:`create`、`read`、`update`、`delete`、`analyze`、`deploy` + +#### Tech Stack 标签(技术栈标签) +- 描述 Skill 涉及的技术栈 +- 示例:`python`、`java`、`react`、`kubernetes`、`postgresql` + +### 2.2 元数据结构设计 + +#### 标准元数据字段 +```json +{ + "complexity": "low|medium|high", + "estimated_time": "5m", + "dependencies": ["skill_id_1", "skill_id_2"], + "required_permissions": ["read_code", "write_files"], + "compatibility": { + "min_agent_version": "1.0.0", + "supported_models": ["claude-sonnet-4.6", "claude-opus-4.6"] + }, + "usage_stats": { + "total_calls": 1000, + "success_rate": 0.95 + } +} +``` + +#### 扩展元数据 +- 自定义字段支持 JSON 格式存储 +- 支持元数据查询和过滤 + +## 3. Skill 匹配算法设计 + +### 3.1 匹配流程架构 + +``` +输入:查询上下文(意图、历史、场景、用户角色) + ↓ +阶段 1:规则过滤 + ├── 活跃状态过滤(is_active = true) + ├── 角色权限过滤 + ├── 技术栈兼容性过滤 + └── 标签前置过滤 + ↓ +阶段 2:语义相似度计算 + ├── 查询向量生成(意图 + 场景 + 上下文) + ├── 向量相似度检索(ANN 搜索) + └── 候选集排序 + ↓ +阶段 3:多维度评分 + ├── 语义相似度分(40%) + ├── 标签匹配分(30%) + ├── 历史使用频率分(20%) + └── 上下文相关性分(10%) + ↓ +阶段 4:结果重排 + ├── 多样性保证(避免重复类型) + ├── 相关性阈值过滤 + └── Top-K 返回 + ↓ +输出:匹配的 Skills 列表(带评分) +``` + +### 3.2 查询向量生成策略 + +#### 组合查询向量 +将以下内容合并生成查询向量: +1. **当前意图文本**:用户当前的请求意图 +2. **场景描述**:当前工作场景的上下文描述 +3. **对话历史摘要**:最近 N 轮对话的语义摘要 +4. **用户角色信息**:用户角色相关的描述文本 + +#### 向量生成方式 +- 方式 A:直接拼接文本,生成单一向量 +- 方式 B:分别生成向量后加权平均 +- 方式 C:生成多个独立向量,分别检索后合并结果 + +### 3.3 相似度计算方法 + +#### 向量相似度 +- 使用余弦相似度(Cosine Similarity) +- 公式:`similarity = (A · B) / (||A|| × ||B||)` +- pgvector 操作符:`<=>`(余弦距离,越小越相似) + +#### 标签匹配度 +- 精确匹配:标签完全一致 +- 层次匹配:父子标签层级匹配 +- 权重计算:不同标签类型设置不同权重 + +#### 上下文相关性 +- 基于对话历史中的 Skill 使用模式 +- 计算 Skill 与历史上下文的关联度 + +### 3.4 多维度评分公式 + +``` +Total Score = w1 × SemanticScore + w2 × TagScore + w3 × HistoryScore + w4 × ContextScore + +其中: +- w1 = 0.4(语义相似度权重) +- w2 = 0.3(标签匹配权重) +- w3 = 0.2(历史使用权重) +- w4 = 0.1(上下文相关性权重) +``` + +## 4. 场景描述处理策略 + +### 4.1 场景描述来源 + +1. **显式场景描述**:用户提供的场景文本 +2. **隐式场景推断**:从对话历史和上下文自动提取 +3. **环境上下文**:当前工作目录、文件类型、Git 状态等 + +### 4.2 场景描述处理流程 + +``` +原始场景输入 + ↓ +文本预处理 + ├── 去除噪声和冗余 + ├── 提取关键实体 + └── 识别技术关键词 + ↓ +场景分类 + ├── 开发场景(coding/debugging/refactoring) + ├── 部署场景(deploy/monitor/maintenance) + └── 分析场景(review/analysis/report) + ↓ +场景增强 + ├── 关联历史相似场景 + ├── 添加相关技术标签 + └── 生成场景向量 + ↓ +输出:结构化场景描述 +``` + +### 4.3 场景描述缓存策略 + +- 热门场景描述缓存(LRU 策略) +- 场景向量预计算 +- 定期清理过期缓存 + +## 5. pgvector 索引策略和检索优化 + +### 5.1 索引类型选择 + +#### HNSW 索引(推荐) +- 优点:查询速度快,适合大规模数据 +- 适用场景:实时检索,查询频繁 +- 参数配置: + - `m = 16`(每个节点的连接数) + - `ef_construction = 64`(构建时的搜索宽度) + +```sql +CREATE INDEX idx_skills_embedding_hnsw +ON skills USING hnsw (embedding vector_cosine_ops) +WITH (m = 16, ef_construction = 64); +``` + +#### IVFFlat 索引 +- 优点:构建速度快,内存占用低 +- 适用场景:数据更新频繁 +- 参数配置: + - `lists = 100`(聚类中心数量) + +```sql +CREATE INDEX idx_skills_embedding_ivfflat +ON skills USING ivfflat (embedding vector_cosine_ops) +WITH (lists = 100); +``` + +### 5.2 检索优化策略 + +#### 批量检索优化 +- 使用 `array_agg` 批量获取结果 +- 减少 SQL 查询次数 + +#### 预过滤优化 +- 先用规则过滤缩小候选集 +- 再在候选集上进行向量检索 + +#### 查询参数调优 +- `ef_search`:控制搜索精度与速度的权衡 +- 推荐值:`ef_search = 40`(平衡性能) + +```sql +SET hnsw.ef_search = 40; +``` + +#### 分页优化 +- 使用游标分页代替 OFFSET +- 避免深度分页性能问题 + +### 5.3 索引维护策略 + +#### 定期重建索引 +- 当数据变更超过 20% 时重建 HNSW 索引 +- 使用 `REINDEX INDEX` 命令 + +#### 向量更新优化 +- 批量更新向量,减少索引重建频率 +- 使用异步任务处理向量计算 + +#### 索引监控 +- 监控索引大小和查询性能 +- 定期收集统计信息 + +```sql +ANALYZE skills; +``` + +### 5.4 查询性能优化 + +#### 查询计划分析 +- 使用 `EXPLAIN ANALYZE` 分析查询性能 +- 识别性能瓶颈并优化 + +#### 结果缓存 +- 缓存热门查询结果 +- 设置合理的缓存过期时间 + +#### 连接池配置 +- 合理配置数据库连接池大小 +- 避免连接频繁创建和销毁 + +## 6. 扩展性设计 + +### 6.1 插件化标签系统 +- 支持自定义标签类型 +- 支持标签权重动态配置 + +### 6.2 多语言向量支持 +- 支持不同语言的向量嵌入 +- 支持多语言混合查询 + +### 6.3 A/B 测试框架 +- 支持不同匹配算法的对比测试 +- 支持实时算法切换 + +### 6.4 可观测性 +- 记录匹配过程的详细日志 +- 统计各项指标(召回率、准确率、响应时间) +- 支持算法效果分析 + +--- + +**设计版本**:v1.0 +**设计日期**:2026-04-05 +**设计人**:Skills 开发工程师 diff --git a/docs/agent-skills-search/doc-01/01-overview.md b/docs/agent-skills-search/doc-01/01-overview.md new file mode 100644 index 00000000..9464566b --- /dev/null +++ b/docs/agent-skills-search/doc-01/01-overview.md @@ -0,0 +1,96 @@ +# Agent Skills 智能检索系统 - 系统概述 + +## 1. 项目背景 + +SkillHub 是一个 Agent 技能注册中心,用于管理 Agent 技能包的发布、版本控制和发现。为了提升 Agent 选择技能的智能化水平,需要构建一个基于向量检索的智能匹配系统。 + +## 2. 核心目标 + +构建一个稳定可靠、精准匹配的技能检索系统,通过以下能力实现: + +- **意图识别**:理解用户查询的真实意图 +- **上下文感知**:结合多轮对话历史,理解用户当前需求 +- **场景适配**:根据使用场景和用户角色,推荐最合适的技能 +- **精准匹配**:结合语义向量、标签、类别等多维度信息进行匹配 + +## 3. 核心输入 + +| 输入项 | 说明 | 示例 | +|--------|------|------| +| 意图识别 | 用户查询的意图类型 | "代码生成"、"数据分析"、"文本处理" | +| 多轮对话上下文 | 用户与 Agent 的历史对话 | 过去 N 轮的问答记录 | +| 场景描述 | 当前使用场景 | "Web 开发"、"数据可视化" | +| 用户角色信息 | 用户身份和权限 | "开发者"、"数据分析师" | +| 标签信息 | 技能的标签分类 | ["python", "react", "api"] | +| 元数据 | 技能的详细元信息 | 版本、依赖、示例代码等 | + +## 4. 技术选型 + +| 组件 | 选型 | 说明 | +|------|------|------| +| 向量数据库 | PostgreSQL + pgvector | 利用现有数据库,减少架构复杂度 | +| 嵌入模型 | OpenAI text-embedding-3-small | 1536 维向量,高质量语义表示 | +| 意图识别 | 基于向量相似度 | 预定义意图类别,通过向量匹配 | +| 向量索引 | ivfflat | 平衡精度和性能 | +| 对话管理 | Redis + PostgreSQL | 热数据缓存,冷数据持久化 | +| 后端框架 | Spring Boot 3.2.3 | 现有技术栈,无缝集成 | + +## 5. 系统特性 + +### 5.1 稳定性 +- 基于成熟的 PostgreSQL 数据库 +- pgvector 扩展经过生产验证 +- 完善的错误处理和降级机制 + +### 5.2 可靠性 +- 多维度评分,避免单点失败 +- 权限控制确保数据安全 +- 异步处理保障响应性能 + +### 5.3 精准匹配 +- 语义向量相似度检索 +- 意图类别过滤 +- 标签精确匹配 +- 多维度权重融合 + +## 6. 性能指标 + +| 指标 | 目标值 | 说明 | +|------|--------|------| +| 查询响应时间 | < 500ms | 95 分位 | +| 并发 QPS | > 100 | 稳定支持 | +| Top-10 准确率 | > 80% | 相关技能在前 10 | +| 意图匹配准确率 | > 85% | 意图分类正确率 | + +## 7. 与现有系统集成 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ SkillHub 现有系统 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Skill 管理 │ │ 搜索服务 │ │ 权限系统 │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ + │ + │ 复用现有能力 + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Agent Skills 智能检索系统 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ 对话管理 │ │ 意图识别 │ │ 智能匹配 │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +## 8. 文档结构 + +| 文档 | 内容 | +|------|------| +| 01-overview.md | 系统概述(本文档) | +| 02-architecture.md | 架构设计 | +| 03-data-model.md | 数据模型 | +| 04-algorithms.md | 算法设计 | +| 05-flow-diagrams.md | 流程图 | +| 06-architecture-diagrams.md | 架构图 | +| 07-api-design.md | API 设计 | +| 08-implementation-guide.md | 实施指南 | diff --git a/docs/agent-skills-search/doc-01/02-architecture.md b/docs/agent-skills-search/doc-01/02-architecture.md new file mode 100644 index 00000000..c9e497f5 --- /dev/null +++ b/docs/agent-skills-search/doc-01/02-architecture.md @@ -0,0 +1,266 @@ +# Agent Skills 智能检索系统 - 架构设计 + +## 1. 系统架构分层 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ API Gateway Layer │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ Agent Skill Search Controller │ │ +│ │ - POST /api/agent/skills/search │ │ +│ │ - POST /api/agent/sessions │ │ +│ │ - GET /api/agent/sessions/{id} │ │ +│ └──────────────────────────────────────────────────────────┘ │ +└─────────────────────────────┬───────────────────────────────────┘ + │ +┌─────────────────────────────▼───────────────────────────────────┐ +│ Service Layer │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Context │ │ Intent │ │ Query │ │ +│ │ Builder │ │ Classifier │ │ Embedder │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Hybrid │ │ Skill │ │ Agent │ │ +│ │ Search │ │ Reranker │ │ Session │ │ +│ │ Service │ │ │ │ Service │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────┬───────────────────────────────────┘ + │ +┌─────────────────────────────▼───────────────────────────────────┐ +│ Domain Layer │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Agent │ │ Skill │ │ Intent │ │ +│ │ Session │ │ Embedding │ │ Mapping │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────┬───────────────────────────────────┘ + │ +┌─────────────────────────────▼───────────────────────────────────┐ +│ Infrastructure Layer │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ PostgreSQL │ │ Redis │ │ OpenAI │ │ +│ │ + pgvector │ │ Cache │ │ Embedding │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +## 2. 核心组件详解 + +### 2.1 Context Builder(上下文构建器) + +**职责**:收集并构建完整的查询上下文 + +**输入**: +- 用户查询文本 +- Session ID +- 用户 ID +- 场景描述 +- 用户角色 + +**输出**:`AgentSearchContext` + +```java +public record AgentSearchContext( + String query, // 查询文本 + List conversationHistory, // 对话历史 + String scenarioDescription, // 场景描述 + String userRole, // 用户角色 + Map metadata // 元数据 +) {} +``` + +### 2.2 Intent Classifier(意图分类器) + +**职责**:识别用户查询的意图类型 + +**实现方式**:基于向量相似度的分类 + +**流程**: +1. 将查询文本转换为向量 +2. 与预定义的意图嵌入计算余弦相似度 +3. 返回 Top-N 意图及置信度 + +```java +public interface IntentClassifier { + IntentClassificationResult classify( + String query, + AgentSearchContext context + ); +} + +public record IntentClassificationResult( + String intentLabel, // 主要意图 + double confidence, // 置信度 + List alternativeIntents // 备选意图 +) {} +``` + +### 2.3 Query Embedder(查询向量化) + +**职责**:将综合查询上下文转换为向量 + +**向量构建公式**: +``` +query_vector = normalize( + w1 * embed(query_text) + + w2 * embed(conversation_context) + + w3 * embed(scenario_description) + + w4 * embed(user_role) + + w5 * intent_embedding +) +``` + +**权重配置**: +- w1 (查询文本): 0.4 +- w2 (对话上下文): 0.2 +- w3 (场景描述): 0.15 +- w4 (用户角色): 0.1 +- w5 (意图): 0.15 + +### 2.4 Hybrid Search Service(混合检索服务) + +**职责**:执行多维度检索 + +**检索流程**: +1. **向量检索**:使用 pgvector 进行语义相似度检索 +2. **意图过滤**:根据识别的意图过滤技能类别 +3. **标签匹配**:匹配用户指定或相关的标签 +4. **权限过滤**:根据用户角色过滤可见技能 + +### 2.5 Skill Reranker(技能重排序器) + +**职责**:对检索结果进行多维度重排序 + +**评分公式**: +``` +final_score = α * vector_similarity + + β * intent_match_score + + γ * tag_match_score + + δ * popularity_score + + ε * rating_score +``` + +**权重配置**: +- α (向量相似度): 0.4 +- β (意图匹配): 0.25 +- γ (标签匹配): 0.2 +- δ (流行度): 0.1 +- ε (评分): 0.05 + +### 2.6 Agent Session Service(会话管理服务) + +**职责**:管理 Agent 对话会话 + +**功能**: +- 创建新会话 +- 保存对话消息 +- 获取会话历史 +- 会话过期管理 + +## 3. 数据流 + +``` +┌──────────────┐ +│ Agent Request│ +└──────┬───────┘ + │ + ▼ +┌─────────────────────────────────┐ +│ 1. Context Builder │ +│ - 收集查询、历史、角色 │ +│ - 构建 SearchContext │ +└──────┬──────────────────────────┘ + │ + ▼ +┌─────────────────────────────────┐ +│ 2. Intent Classifier │ +│ - 向量化查询 │ +│ - 匹配意图 │ +└──────┬──────────────────────────┘ + │ + ▼ +┌─────────────────────────────────┐ +│ 3. Query Embedder │ +│ - 融合多维度信息 │ +│ - 生成查询向量 │ +└──────┬──────────────────────────┘ + │ + ▼ +┌─────────────────────────────────┐ +│ 4. Hybrid Search │ +│ - 向量检索 (pgvector) │ +│ - 意图/标签/权限过滤 │ +└──────┬──────────────────────────┘ + │ + ▼ +┌─────────────────────────────────┐ +│ 5. Skill Reranker │ +│ - 多维度评分 │ +│ - 重排序结果 │ +└──────┬──────────────────────────┘ + │ + ▼ +┌─────────────────────────────────┐ +│ 6. Return Results │ +│ - 返回匹配技能列表 │ +│ - 包含匹配原因 │ +└─────────────────────────────────┘ +``` + +## 4. 模块依赖关系 + +``` +Agent Skill Search Controller + │ + ├─► AgentContextBuilder + │ └─► AgentSessionService + │ └─► Redis / PostgreSQL + │ + ├─► IntentClassifier + │ ├─► QueryEmbedder + │ └─► IntentMappingRepository + │ └─► PostgreSQL + │ + ├─► HybridSkillSearchService + │ ├─► QueryEmbedder + │ ├─► SkillEmbeddingRepository + │ ├─► IntentClassifier + │ └─► SkillReranker + │ + └─► SkillReranker + ├─► SkillRepository + └─► LabelRepository +``` + +## 5. 外部依赖 + +| 依赖 | 用途 | 调用方式 | +|------|------|----------| +| PostgreSQL | 数据持久化、向量检索 | JPA / Native SQL | +| Redis | 会话缓存、热数据存储 | Spring Data Redis | +| OpenAI API | 嵌入向量生成 | HTTP REST API | + +## 6. 缓存策略 + +| 数据类型 | 缓存位置 | TTL | 更新策略 | +|----------|----------|-----|----------| +| 活跃会话 | Redis | 1小时 | 每次访问更新 | +| 意图嵌入 | Redis | 永久 | 管理接口更新 | +| 技能嵌入 | PostgreSQL | - | 版本更新时 | +| 查询结果 | Redis | 5分钟 | 主动失效 | + +## 7. 错误处理 + +| 场景 | 处理策略 | +|------|----------| +| OpenAI API 调用失败 | 降级到基于关键词的检索 | +| 向量索引未就绪 | 使用全文搜索 | +| 会话不存在 | 创建新会话 | +| 意图识别失败 | 使用通用意图 "general" | + +## 8. 扩展点 + +1. **嵌入模型切换**:支持配置不同的嵌入模型 +2. **意图库扩展**:通过数据库动态添加新意图 +3. **评分策略**:可配置的权重参数 +4. **检索后处理**:支持自定义业务规则过滤 diff --git a/docs/agent-skills-search/doc-01/03-data-model.md b/docs/agent-skills-search/doc-01/03-data-model.md new file mode 100644 index 00000000..4dcb02cb --- /dev/null +++ b/docs/agent-skills-search/doc-01/03-data-model.md @@ -0,0 +1,573 @@ +# Agent Skills 智能检索系统 - 数据模型 + +## 1. 数据库扩展 + +### 1.1 pgvector 扩展安装 + +```sql +-- 在 PostgreSQL 中安装 pgvector 扩展 +CREATE EXTENSION IF NOT EXISTS vector; + +-- 验证安装 +SELECT * FROM pg_extension WHERE extname = 'vector'; +``` + +## 2. 核心数据表 + +### 2.1 agent_session(Agent 会话表) + +存储 Agent 与用户的对话会话信息。 + +```sql +CREATE TABLE agent_session ( + -- 主键 + id BIGSERIAL PRIMARY KEY, + + -- 标识信息 + agent_id VARCHAR(128) NOT NULL, + user_id VARCHAR(128) NOT NULL, + session_id VARCHAR(128) UNIQUE NOT NULL, + + -- 上下文信息 + scenario_description TEXT, + user_role VARCHAR(128), + + -- 元数据(JSONB 格式,灵活扩展) + metadata JSONB DEFAULT '{}', + + -- 时间戳 + started_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + ended_at TIMESTAMP WITH TIME ZONE, + + -- 索引 + CONSTRAINT fk_agent_session_user FOREIGN KEY (user_id) REFERENCES "user"(id) ON DELETE CASCADE +); + +-- 创建索引 +CREATE INDEX idx_agent_session_agent_id ON agent_session(agent_id); +CREATE INDEX idx_agent_session_user_id ON agent_session(user_id); +CREATE INDEX idx_agent_session_session_id ON agent_session(session_id); +CREATE INDEX idx_agent_session_started_at ON agent_session(started_at DESC); + +-- GIN 索引用于 JSONB 查询 +CREATE INDEX idx_agent_session_metadata ON agent_session USING GIN(metadata); +``` + +**字段说明**: + +| 字段 | 类型 | 说明 | +|------|------|------| +| id | BIGSERIAL | 主键 | +| agent_id | VARCHAR(128) | Agent 标识符 | +| user_id | VARCHAR(128) | 用户 ID | +| session_id | VARCHAR(128) | 会话唯一标识 | +| scenario_description | TEXT | 场景描述 | +| user_role | VARCHAR(128) | 用户角色 | +| metadata | JSONB | 扩展元数据 | +| started_at | TIMESTAMPTZ | 会话开始时间 | +| updated_at | TIMESTAMPTZ | 会话更新时间 | +| ended_at | TIMESTAMPTZ | 会话结束时间 | + +### 2.2 agent_message(对话消息表) + +存储会话中的每条消息。 + +```sql +CREATE TABLE agent_message ( + -- 主键 + id BIGSERIAL PRIMARY KEY, + + -- 关联会话 + session_id BIGINT NOT NULL, + + -- 消息内容 + role VARCHAR(32) NOT NULL, -- 'user' | 'assistant' | 'system' + content TEXT NOT NULL, + + -- 意图识别结果 + intent_label VARCHAR(128), + intent_confidence DECIMAL(5,4), + + -- 向量嵌入 + embedding vector(1536), + + -- 元数据 + metadata JSONB DEFAULT '{}', + + -- 时间戳 + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + + -- 外键约束 + CONSTRAINT fk_agent_message_session + FOREIGN KEY (session_id) + REFERENCES agent_session(id) + ON DELETE CASCADE, + + -- 检查约束 + CONSTRAINT chk_agent_message_role + CHECK (role IN ('user', 'assistant', 'system')), + + CONSTRAINT chk_agent_message_confidence + CHECK (intent_confidence IS NULL OR + (intent_confidence >= 0 AND intent_confidence <= 1)) +); + +-- 创建索引 +CREATE INDEX idx_agent_message_session_id ON agent_message(session_id); +CREATE INDEX idx_agent_message_created_at ON agent_message(created_at DESC); +CREATE INDEX idx_agent_message_intent ON agent_message(intent_label); + +-- 向量索引(需要先有足够数据) +-- CREATE INDEX idx_agent_message_embedding ON agent_message +-- USING ivfflat(embedding vector_cosine_ops) WITH (lists = 100); + +-- GIN 索引用于 JSONB 查询 +CREATE INDEX idx_agent_message_metadata ON agent_message USING GIN(metadata); +``` + +**字段说明**: + +| 字段 | 类型 | 说明 | +|------|------|------| +| id | BIGSERIAL | 主键 | +| session_id | BIGINT | 关联的会话 ID | +| role | VARCHAR(32) | 消息角色 | +| content | TEXT | 消息内容 | +| intent_label | VARCHAR(128) | 识别的意图标签 | +| intent_confidence | DECIMAL(5,4) | 意图置信度 | +| embedding | vector(1536) | 消息向量 | +| metadata | JSONB | 扩展元数据 | +| created_at | TIMESTAMPTZ | 创建时间 | + +### 2.3 skill_embedding(技能向量表) + +存储技能的向量嵌入,用于语义检索。 + +```sql +CREATE TABLE skill_embedding ( + -- 主键 + id BIGSERIAL PRIMARY KEY, + + -- 关联技能 + skill_id BIGINT NOT NULL, + skill_version_id BIGINT, + + -- 嵌入类型和向量 + embedding_type VARCHAR(32) NOT NULL, + embedding vector(1536) NOT NULL, + + -- 元数据 + metadata JSONB DEFAULT '{}', + + -- 时间戳 + updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + + -- 外键约束 + CONSTRAINT fk_skill_embedding_skill + FOREIGN KEY (skill_id) + REFERENCES skill(id) + ON DELETE CASCADE, + + CONSTRAINT fk_skill_embedding_version + FOREIGN KEY (skill_version_id) + REFERENCES skill_version(id) + ON DELETE SET NULL, + + -- 唯一约束 + CONSTRAINT uk_skill_embedding UNIQUE(skill_id, embedding_type), + + -- 检查约束 + CONSTRAINT chk_skill_embedding_type + CHECK (embedding_type IN ('description', 'example', 'usage', 'combined')) +); + +-- 创建索引 +CREATE INDEX idx_skill_embedding_skill_id ON skill_embedding(skill_id); +CREATE INDEX idx_skill_embedding_version_id ON skill_embedding(skill_version_id); + +-- 向量索引(ivfflat 类型,平衡精度和性能) +CREATE INDEX idx_skill_embedding_embedding ON skill_embedding + USING ivfflat(embedding vector_cosine_ops) + WITH (lists = 100); + +-- GIN 索引用于 JSONB 查询 +CREATE INDEX idx_skill_embedding_metadata ON skill_embedding USING GIN(metadata); +``` + +**embedding_type 枚举值**: + +| 类型 | 说明 | +|------|------| +| description | 技能描述向量化 | +| example | 示例代码向量化 | +| usage | 使用说明向量化 | +| combined | 综合向量 | + +### 2.4 intent_mapping(意图映射表) + +存储意图类别及其相关配置。 + +```sql +CREATE TABLE intent_mapping ( + -- 主键 + id BIGSERIAL PRIMARY KEY, + + -- 意图信息 + intent_label VARCHAR(128) UNIQUE NOT NULL, + description TEXT, + + -- 关联的技能类别 + skill_categories TEXT[], + + -- 示例查询(用于意图识别) + example_queries TEXT[], + + -- 意图向量 + embedding vector(1536) NOT NULL, + + -- 优先级和状态 + priority INTEGER DEFAULT 0, + active BOOLEAN DEFAULT true, + + -- 时间戳 + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + + -- 检查约束 + CONSTRAINT chk_intent_mapping_priority + CHECK (priority >= 0) +); + +-- 创建索引 +CREATE INDEX idx_intent_mapping_label ON intent_mapping(intent_label); +CREATE INDEX idx_intent_mapping_active ON intent_mapping(active); + +-- 向量索引 +CREATE INDEX idx_intent_mapping_embedding ON intent_mapping + USING ivfflat(embedding vector_cosine_ops) + WITH (lists = 50); + +-- GIN 索引用于数组查询 +CREATE INDEX idx_intent_mapping_categories ON intent_mapping + USING GIN(skill_categories); +``` + +## 3. Java 领域模型 + +### 3.1 AgentSession + +```java +package com.iflytek.skillhub.domain.agent; + +import jakarta.persistence.*; +import java.time.Instant; +import java.util.Map; + +@Entity +@Table(name = "agent_session") +public class AgentSession { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "agent_id", nullable = false, length = 128) + private String agentId; + + @Column(name = "user_id", nullable = false, length = 128) + private String userId; + + @Column(name = "session_id", nullable = false, unique = true, length = 128) + private String sessionId; + + @Column(name = "scenario_description", columnDefinition = "TEXT") + private String scenarioDescription; + + @Column(name = "user_role", length = 128) + private String userRole; + + @JdbcTypeCode(SqlTypes.JSON) + @Column(name = "metadata", columnDefinition = "jsonb") + private Map metadata = Map.of(); + + @Column(name = "started_at", nullable = false) + private Instant startedAt = Instant.now(); + + @Column(name = "updated_at", nullable = false) + private Instant updatedAt = Instant.now(); + + @Column(name = "ended_at") + private Instant endedAt; + + @PreUpdate + protected void onUpdate() { + updatedAt = Instant.now(); + } + + // Getters and Setters... +} +``` + +### 3.2 AgentMessage + +```java +package com.iflytek.skillhub.domain.agent; + +import jakarta.persistence.*; +import java.math.BigDecimal; +import java.time.Instant; +import java.util.Map; + +@Entity +@Table(name = "agent_message") +public class AgentMessage { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "session_id", nullable = false) + private Long sessionId; + + @Enumerated(EnumType.STRING) + @Column(name = "role", nullable = false, length = 32) + private MessageRole role; + + @Column(name = "content", nullable = false, columnDefinition = "TEXT") + private String content; + + @Column(name = "intent_label", length = 128) + private String intentLabel; + + @Column(name = "intent_confidence", precision = 5, scale = 4) + private BigDecimal intentConfidence; + + // 注意:pgvector 的 Java 类型需要自定义类型处理器 + // 这里使用 String 存储序列化后的向量 + @Column(name = "embedding", columnDefinition = "vector(1536)") + private String embedding; + + @JdbcTypeCode(SqlTypes.JSON) + @Column(name = "metadata", columnDefinition = "jsonb") + private Map metadata = Map.of(); + + @Column(name = "created_at", nullable = false) + private Instant createdAt = Instant.now(); + + public enum MessageRole { + USER, ASSISTANT, SYSTEM + } + + // Getters and Setters... +} +``` + +### 3.3 SkillEmbedding + +```java +package com.iflytek.skillhub.domain.agent; + +import jakarta.persistence.*; +import java.time.Instant; +import java.util.Map; + +@Entity +@Table(name = "skill_embedding") +public class SkillEmbedding { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "skill_id", nullable = false) + private Long skillId; + + @Column(name = "skill_version_id") + private Long skillVersionId; + + @Enumerated(EnumType.STRING) + @Column(name = "embedding_type", nullable = false, length = 32) + private EmbeddingType embeddingType; + + @Column(name = "embedding", nullable = false, columnDefinition = "vector(1536)") + private String embedding; + + @JdbcTypeCode(SqlTypes.JSON) + @Column(name = "metadata", columnDefinition = "jsonb") + private Map metadata = Map.of(); + + @Column(name = "updated_at", nullable = false) + private Instant updatedAt = Instant.now(); + + @PreUpdate + protected void onUpdate() { + updatedAt = Instant.now(); + } + + public enum EmbeddingType { + DESCRIPTION, EXAMPLE, USAGE, COMBINED + } + + // Getters and Setters... +} +``` + +### 3.4 IntentMapping + +```java +package com.iflytek.skillhub.domain.agent; + +import jakarta.persistence.*; +import java.time.Instant; +import java.util.List; +import java.util.Map; + +@Entity +@Table(name = "intent_mapping") +public class IntentMapping { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "intent_label", nullable = false, unique = true, length = 128) + private String intentLabel; + + @Column(name = "description", columnDefinition = "TEXT") + private String description; + + @ElementCollection + @CollectionTable(name = "intent_skill_categories", joinColumns = @JoinColumn(name = "intent_id")) + @Column(name = "category") + private List skillCategories; + + @ElementCollection + @CollectionTable(name = "intent_example_queries", joinColumns = @JoinColumn(name = "intent_id")) + @Column(name = "query") + private List exampleQueries; + + @Column(name = "embedding", nullable = false, columnDefinition = "vector(1536)") + private String embedding; + + @Column(name = "priority", nullable = false) + private Integer priority = 0; + + @Column(name = "active", nullable = false) + private Boolean active = true; + + @Column(name = "created_at", nullable = false) + private Instant createdAt = Instant.now(); + + @Column(name = "updated_at", nullable = false) + private Instant updatedAt = Instant.now(); + + @PreUpdate + protected void onUpdate() { + updatedAt = Instant.now(); + } + + // Getters and Setters... +} +``` + +## 4. 初始数据 + +### 4.1 预定义意图类别 + +```sql +-- 插入预定义意图 +INSERT INTO intent_mapping (intent_label, description, skill_categories, example_queries, priority, active) VALUES +('code_generation', '代码生成相关技能', ARRAY['coding', 'development'], ARRAY['写一个函数', '生成代码', '创建类'], 10, true), +('data_analysis', '数据分析相关技能', ARRAY['data', 'analysis', 'visualization'], ARRAY['分析数据', '绘制图表', '数据统计'], 10, true), +('text_processing', '文本处理相关技能', ARRAY['text', 'nlp', 'language'], ARRAY['处理文本', '提取关键词', '文本分类'], 10, true), +('api_integration', 'API 集成相关技能', ARRAY['api', 'integration', 'web'], ARRAY['调用 API', 'HTTP 请求', 'REST API'], 10, true), +('file_processing', '文件处理相关技能', ARRAY['file', 'io', 'storage'], ARRAY['读取文件', '写入文件', '文件转换'], 10, true), +('database', '数据库相关技能', ARRAY['database', 'sql', 'storage'], ARRAY['查询数据库', 'SQL 语句', '数据库操作'], 10, true), +('general', '通用查询', ARRAY['general'], ARRAY['帮助', '能做什么', '功能列表'], 0, true); +``` + +## 5. 数据迁移 + +### 5.1 Flyway 迁移脚本 + +```sql +-- V__create_agent_tables.sql + +-- 1. 安装 pgvector 扩展 +CREATE EXTENSION IF NOT EXISTS vector; + +-- 2. 创建 agent_session 表 +CREATE TABLE agent_session ( + id BIGSERIAL PRIMARY KEY, + agent_id VARCHAR(128) NOT NULL, + user_id VARCHAR(128) NOT NULL, + session_id VARCHAR(128) UNIQUE NOT NULL, + scenario_description TEXT, + user_role VARCHAR(128), + metadata JSONB DEFAULT '{}', + started_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + ended_at TIMESTAMP WITH TIME ZONE +); + +-- 3. 创建 agent_message 表 +CREATE TABLE agent_message ( + id BIGSERIAL PRIMARY KEY, + session_id BIGINT NOT NULL, + role VARCHAR(32) NOT NULL CHECK (role IN ('user', 'assistant', 'system')), + content TEXT NOT NULL, + intent_label VARCHAR(128), + intent_confidence DECIMAL(5,4) CHECK (intent_confidence IS NULL OR (intent_confidence >= 0 AND intent_confidence <= 1)), + embedding vector(1536), + metadata JSONB DEFAULT '{}', + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + CONSTRAINT fk_agent_message_session FOREIGN KEY (session_id) REFERENCES agent_session(id) ON DELETE CASCADE +); + +-- 4. 创建 skill_embedding 表 +CREATE TABLE skill_embedding ( + id BIGSERIAL PRIMARY KEY, + skill_id BIGINT NOT NULL, + skill_version_id BIGINT, + embedding_type VARCHAR(32) NOT NULL CHECK (embedding_type IN ('description', 'example', 'usage', 'combined')), + embedding vector(1536) NOT NULL, + metadata JSONB DEFAULT '{}', + updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + CONSTRAINT uk_skill_embedding UNIQUE(skill_id, embedding_type), + CONSTRAINT fk_skill_embedding_skill FOREIGN KEY (skill_id) REFERENCES skill(id) ON DELETE CASCADE +); + +-- 5. 创建 intent_mapping 表 +CREATE TABLE intent_mapping ( + id BIGSERIAL PRIMARY KEY, + intent_label VARCHAR(128) UNIQUE NOT NULL, + description TEXT, + skill_categories TEXT[], + example_queries TEXT[], + embedding vector(1536) NOT NULL, + priority INTEGER DEFAULT 0 CHECK (priority >= 0), + active BOOLEAN DEFAULT true, + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() +); + +-- 6. 创建索引 +CREATE INDEX idx_agent_session_agent_id ON agent_session(agent_id); +CREATE INDEX idx_agent_session_user_id ON agent_session(user_id); +CREATE INDEX idx_agent_session_session_id ON agent_session(session_id); +CREATE INDEX idx_agent_session_metadata ON agent_session USING GIN(metadata); + +CREATE INDEX idx_agent_message_session_id ON agent_message(session_id); +CREATE INDEX idx_agent_message_intent ON agent_message(intent_label); +CREATE INDEX idx_agent_message_metadata ON agent_message USING GIN(metadata); + +CREATE INDEX idx_skill_embedding_skill_id ON skill_embedding(skill_id); +CREATE INDEX idx_skill_embedding_embedding ON skill_embedding USING ivfflat(embedding vector_cosine_ops) WITH (lists = 100); +CREATE INDEX idx_skill_embedding_metadata ON skill_embedding USING GIN(metadata); + +CREATE INDEX idx_intent_mapping_label ON intent_mapping(intent_label); +CREATE INDEX idx_intent_mapping_active ON intent_mapping(active); +CREATE INDEX idx_intent_mapping_embedding ON intent_mapping USING ivfflat(embedding vector_cosine_ops) WITH (lists = 50); +CREATE INDEX idx_intent_mapping_categories ON intent_mapping USING GIN(skill_categories); +``` diff --git a/docs/agent-skills-search/doc-01/04-algorithms.md b/docs/agent-skills-search/doc-01/04-algorithms.md new file mode 100644 index 00000000..62e034ca --- /dev/null +++ b/docs/agent-skills-search/doc-01/04-algorithms.md @@ -0,0 +1,445 @@ +# Agent Skills 智能检索系统 - 算法设计 + +## 1. 向量嵌入生成 + +### 1.1 嵌入模型配置 + +使用 OpenAI `text-embedding-3-small` 模型: +- 维度:1536 +- 输入长度:最多 8191 tokens +- 输出格式:浮点数数组 + +### 1.2 技能向量生成 + +**输入文本构建**: +``` +skill_text = skill_name + "\n" + + skill_description + "\n" + + skill_keywords + "\n" + + usage_examples +``` + +**生成流程**: +```python +def generate_skill_embedding(skill): + # 构建输入文本 + text = build_skill_text(skill) + + # 调用 OpenAI API + response = openai.Embedding.create( + model="text-embedding-3-small", + input=text + ) + + # 返回向量 + return response['data'][0]['embedding'] +``` + +**存储策略**: +- 为每个技能生成 4 种类型的嵌入 + - `description`: 仅技能描述 + - `example`: 仅示例代码 + - `usage`: 仅使用说明 + - `combined`: 综合所有内容 + +## 2. 意图识别算法 + +### 2.1 基于向量相似度的意图分类 + +**算法流程**: + +``` +1. 将用户查询转换为向量 + query_vector = embed(query_text) + +2. 与所有活跃意图的嵌入计算余弦相似度 + for each intent in active_intents: + similarity = cosine_similarity(query_vector, intent.embedding) + +3. 按相似度排序,取 Top-N + top_intents = sort_by_similarity(all_similarities)[:N] + +4. 返回结果 + return top_intents[0] as primary_intent +``` + +**相似度计算**: +```sql +-- 使用 pgvector 的 <=> 操作符 +SELECT + intent_label, + 1 - (embedding <=> :query_vector) as similarity +FROM intent_mapping +WHERE active = true +ORDER BY embedding <=> :query_vector +LIMIT 5; +``` + +**置信度处理**: +- 最高相似度 < 0.3:返回默认意图 "general" +- 最高相似度 >= 0.3:返回识别的意图 +- 返回 Top-3 备选意图 + +### 2.2 意图库更新 + +当添加新意图时: +1. 收集该意图的示例查询 +2. 生成意图嵌入向量(使用示例查询的平均向量) +3. 插入 `intent_mapping` 表 + +## 3. 查询向量构建 + +### 3.1 多维度向量融合 + +**公式**: +``` +query_vector = normalize( + w1 * embed(query_text) + + w2 * embed(conversation_context) + + w3 * embed(scenario_description) + + w4 * embed(user_role) + + w5 * intent_embedding +) +``` + +**权重配置**: + +| 权重 | 值 | 说明 | +|------|-----|------| +| w1 | 0.4 | 查询文本(最重要) | +| w2 | 0.2 | 对话上下文 | +| w3 | 0.15 | 场景描述 | +| w4 | 0.1 | 用户角色 | +| w5 | 0.15 | 意图向量 | + +**归一化**: +```python +def normalize(vector): + norm = np.linalg.norm(vector) + if norm == 0: + return vector + return vector / norm +``` + +### 3.2 对话上下文编码 + +**策略**:使用最近 N 轮对话的摘要 + +```python +def encode_conversation(messages, max_turns=5): + # 取最近 N 轮对话 + recent_messages = messages[-2*max_turns:] + + # 构建上下文文本 + context_text = "\n".join([ + f"{msg.role}: {msg.content}" + for msg in recent_messages + ]) + + # 生成嵌入 + return embed(context_text) +``` + +## 4. 混合检索算法 + +### 4.1 向量检索(Vector Search) + +**SQL 查询**: +```sql +SELECT + se.skill_id, + s.name, + s.summary, + 1 - (se.embedding <=> :query_vector) as similarity +FROM skill_embedding se +JOIN skill s ON s.id = se.skill_id +WHERE se.embedding_type = 'description' + AND s.status = 'ACTIVE' +ORDER BY se.embedding <=> :query_vector +LIMIT 200; +``` + +**向量索引**: +```sql +CREATE INDEX idx_skill_embedding_embedding ON skill_embedding + USING ivfflat(embedding vector_cosine_ops) + WITH (lists = 100); +``` + +### 4.2 意图过滤(Intent Filter) + +**过滤逻辑**: +```sql +SELECT vc.skill_id, vc.similarity +FROM vector_candidates vc +JOIN skill s ON s.id = vc.skill_id +WHERE s.category = ANY(:intent_categories) + OR vc.similarity > 0.7; -- 高相似度可跨意图 +``` + +### 4.3 标签匹配(Tag Matching) + +**精确匹配**: +```sql +SELECT s.id, COUNT(*) as match_count +FROM skill s +JOIN skill_label sl ON sl.skill_id = s.id +JOIN label_definition ld ON ld.id = sl.label_id +WHERE s.id IN (:candidate_ids) + AND ld.slug = ANY(:user_tags) +GROUP BY s.id; +``` + +**模糊匹配**: +- 计算标签向量与查询向量的相似度 +- 相似度 > 0.6 的标签视为匹配 + +### 4.4 权限过滤(Permission Filter) + +```sql +-- 公开技能 +visibility = 'PUBLIC' + +-- 用户私有技能 +visibility = 'PRIVATE' AND (owner_id = :user_id OR namespace_id IN (:admin_namespaces)) + +-- 命名空间内可见 +visibility = 'NAMESPACE_ONLY' AND namespace_id IN (:member_namespaces) +``` + +### 4.5 综合检索 SQL + +```sql +WITH vector_candidates AS ( + SELECT + se.skill_id, + 1 - (se.embedding <=> :query_vector) as vector_score + FROM skill_embedding se + JOIN skill s ON s.id = se.skill_id + WHERE se.embedding_type = 'description' + AND s.status = 'ACTIVE' + ORDER BY se.embedding <=> :query_vector + LIMIT 200 +), +intent_filtered AS ( + SELECT + vc.skill_id, + vc.vector_score + FROM vector_candidates vc + JOIN skill s ON s.id = vc.skill_id + WHERE s.category = ANY(:intent_categories) + OR vc.vector_score > 0.7 +), +permission_filtered AS ( + SELECT + if.skill_id, + if.vector_score + FROM intent_filtered if + JOIN skill s ON s.id = if.skill_id + WHERE (s.visibility = 'PUBLIC') + OR (s.visibility = 'NAMESPACE_ONLY' AND s.namespace_id = ANY(:member_namespace_ids)) + OR (s.visibility = 'PRIVATE' AND (s.owner_id = :user_id OR s.namespace_id = ANY(:admin_namespace_ids))) +), +tag_matched AS ( + SELECT + pf.skill_id, + pf.vector_score, + COUNT(*) FILTER (WHERE ld.slug = ANY(:user_tags)) as tag_count + FROM permission_filtered pf + LEFT JOIN skill_label sl ON sl.skill_id = pf.skill_id + LEFT JOIN label_definition ld ON ld.id = sl.label_id + GROUP BY pf.skill_id, pf.vector_score +) +SELECT + tm.skill_id, + s.name, + s.summary, + s.description, + tm.vector_score, + tm.tag_count, + s.download_count, + s.rating_avg +FROM tag_matched tm +JOIN skill s ON s.id = tm.skill_id +ORDER BY tm.vector_score DESC +LIMIT :limit; +``` + +## 5. 重排序算法 + +### 5.1 多维度评分 + +**评分公式**: +``` +final_score = α * normalize(vector_score) + + β * normalize(intent_match_score) + + γ * normalize(tag_match_score) + + δ * normalize(popularity_score) + + ε * normalize(rating_score) +``` + +**权重配置**: + +| 权重 | 值 | 说明 | +|------|-----|------| +| α | 0.4 | 向量相似度 | +| β | 0.25 | 意图匹配度 | +| γ | 0.2 | 标签匹配度 | +| δ | 0.1 | 流行度(下载次数) | +| ε | 0.05 | 用户评分 | + +### 5.2 各维度计算 + +**1. 向量相似度**: +``` +vector_score = 1 - (skill_embedding <=> query_embedding) +范围:[0, 1] +``` + +**2. 意图匹配度**: +``` +intent_match_score = 1.0 # 如果技能类别匹配意图 + 0.7 # 如果技能类别在意图的相关类别中 + 0.3 # 其他 +``` + +**3. 标签匹配度**: +``` +tag_match_score = min(tag_count / max_user_tags, 1.0) +范围:[0, 1] +``` + +**4. 流行度**: +``` +popularity_score = download_count / max_download_count +使用对数缩放:log(1 + download_count) / log(1 + max_download_count) +``` + +**5. 用户评分**: +``` +rating_score = rating_avg / 5.0 +范围:[0, 1] +``` + +### 5.3 重排序实现 + +```java +public class SkillReranker { + + private final double wVector = 0.4; + private final double wIntent = 0.25; + private final double wTag = 0.2; + private final double wPopularity = 0.1; + private final double wRating = 0.05; + + public List rerank( + List candidates, + IntentClassificationResult intent, + Set userTags, + double maxDownloadCount + ) { + // 计算每个候选技能的综合分数 + return candidates.stream() + .map(candidate -> calculateScore(candidate, intent, userTags, maxDownloadCount)) + .sorted(Comparator.comparingDouble(SkillMatchResult::finalScore).reversed()) + .collect(Collectors.toList()); + } + + private SkillMatchResult calculateScore( + SkillCandidate candidate, + IntentClassificationResult intent, + Set userTags, + double maxDownloadCount + ) { + double vectorScore = candidate.vectorSimilarity(); + double intentScore = calculateIntentScore(candidate, intent); + double tagScore = calculateTagScore(candidate, userTags); + double popularityScore = Math.log(1 + candidate.downloadCount()) + / Math.log(1 + maxDownloadCount); + double ratingScore = candidate.ratingAvg() / 5.0; + + double finalScore = wVector * vectorScore + + wIntent * intentScore + + wTag * tagScore + + wPopularity * popularityScore + + wRating * ratingScore; + + return new SkillMatchResult( + candidate.skillId(), + candidate.name(), + candidate.summary(), + vectorScore, + intentScore, + tagScore, + finalScore, + buildMatchReason(vectorScore, intentScore, tagScore) + ); + } +} +``` + +## 6. 缓存算法 + +### 6.1 查询结果缓存 + +**缓存键**: +``` +cache_key = "agent_search:" + + hash(query_text + ":" + + intent_label + ":" + + sorted(user_tags) + ":" + + user_role + ":" + + scenario_description) +``` + +**TTL**:5 分钟 + +### 6.2 嵌入向量缓存 + +**缓存策略**: +- 技能嵌入:永久缓存(版本更新时失效) +- 意图嵌入:永久缓存(意图更新时失效) +- 查询嵌入:TTL 1 小时 + +## 7. 降级策略 + +| 场景 | 降级方案 | +|------|----------| +| OpenAI API 调用失败 | 使用本地哈希向量 | +| 向量索引未就绪 | 使用全文搜索 | +| 意图识别失败 | 使用默认意图 | +| 响应超时 | 返回部分结果 | + +## 8. 性能优化 + +### 8.1 向量索引调优 + +```sql +-- ivfflat 索引参数 +-- lists = sqrt(行数) +-- 1000 行:lists = 32 +-- 10000 行:lists = 100 +-- 100000 行:lists = 316 +``` + +### 8.2 查询优化 + +1. **限制候选集**:向量检索先返回 Top-200,再过滤 +2. **异步处理**:非阻塞式嵌入生成 +3. **批量查询**:减少数据库往返 + +### 8.3 批量向量化 + +```python +def batch_embed(texts, batch_size=100): + """批量生成嵌入向量""" + all_embeddings = [] + for i in range(0, len(texts), batch_size): + batch = texts[i:i + batch_size] + response = openai.Embedding.create( + model="text-embedding-3-small", + input=batch + ) + all_embeddings.extend([item['embedding'] for item in response['data']]) + return all_embeddings +``` diff --git a/docs/agent-skills-search/doc-01/05-flow-diagrams.md b/docs/agent-skills-search/doc-01/05-flow-diagrams.md new file mode 100644 index 00000000..cc49882f --- /dev/null +++ b/docs/agent-skills-search/doc-01/05-flow-diagrams.md @@ -0,0 +1,255 @@ +# Agent Skills 智能检索系统 - 流程图 + +## 1. 主检索流程 + +```mermaid +flowchart TD + A[Agent 发起技能搜索请求] --> B[Context Builder
收集上下文] + B --> C{检查 Session} + C -->|存在| D[从 Redis/PG 加载历史对话] + C -->|不存在| E[创建新 Session] + D --> F[Intent Classifier
意图识别] + E --> F + F --> G[Query Embedder
构建查询向量] + G --> H[Hybrid Search Service
混合检索] + H --> I[向量检索
pgvector 相似度计算] + I --> J[意图过滤] + J --> K[标签匹配] + K --> L[权限过滤] + L --> M[Skill Reranker
多维度重排序] + M --> N[Result Enricher
结果丰富化] + N --> O[异步保存对话记录] + O --> P[返回匹配技能列表] + + style A fill:#e1f5ff + style P fill:#c8e6c9 + style F fill:#fff9c4 + style H fill:#fff9c4 + style M fill:#fff9c4 +``` + +## 2. 意图识别流程 + +```mermaid +flowchart TD + A[接收用户查询] --> B[文本预处理
清理、分词] + B --> C[调用 OpenAI Embedding API
生成查询向量] + C --> D[查询活跃意图列表] + D --> E[遍历意图嵌入] + E --> F[计算余弦相似度] + F --> G{是否还有意图?} + G -->|是| E + G -->|否| H[按相似度降序排序] + H --> I{最高相似度 >= 0.3?} + I -->|是| J[返回 Top-N 意图
包含置信度] + I -->|否| K[返回默认意图 'general'] + J --> L[输出意图分类结果] + K --> L + + style C fill:#ffebee + style F fill:#e3f2fd + style J fill:#c8e6c9 +``` + +## 3. 向量检索流程 + +```mermaid +flowchart TD + A[接收查询向量] --> B[构建 pgvector 查询] + B --> C[执行 SQL 查询
使用 <=> 操作符] + C --> D{向量索引可用?} + D -->|是| E[使用 ivfflat 索引
快速检索] + D -->|否| F[暴力扫描计算] + E --> G[返回 Top-K 候选] + F --> G + G --> H[过滤非活跃技能] + H --> I[应用可见性过滤] + I --> J[返回候选技能列表] + + style C fill:#e3f2fd + style E fill:#c8e6c9 + style F fill:#fff3e0 +``` + +## 4. 混合检索详细流程 + +```mermaid +flowchart TD + A[开始混合检索] --> B[阶段 1: 向量检索] + B --> B1[查询 pgvector] + B1 --> B2[获取 Top-200 候选] + B2 --> C[阶段 2: 意图过滤] + C --> C1{技能类别匹配意图?} + C1 -->|是| C2[保留候选] + C1 -->|否| C3{向量相似度 > 0.7?} + C3 -->|是| C2 + C3 -->|否| C4[丢弃候选] + C2 --> D[阶段 3: 标签匹配] + D --> D1[统计匹配标签数] + D1 --> E[阶段 4: 权限过滤] + E --> E1{用户有权限访问?} + E1 -->|是| E2[保留候选] + E1 -->|否| C4 + E2 --> F[返回过滤后的候选] + + style B fill:#e3f2fd + style C fill:#fff9c4 + style D fill:#fff9c4 + style E fill:#fff9c4 + style F fill:#c8e6c9 + style C4 fill:#ffcdd2 +``` + +## 5. 重排序流程 + +```mermaid +flowchart TD + A[接收候选技能列表] --> B[计算各维度分数] + B --> B1[向量相似度: 40%] + B --> B2[意图匹配度: 25%] + B --> B3[标签匹配度: 20%] + B --> B4[流行度: 10%] + B --> B5[用户评分: 5%] + B1 --> C[计算综合分数] + B2 --> C + B3 --> C + B4 --> C + B5 --> C + C --> D[按综合分数降序排序] + D --> E[取 Top-N 结果] + E --> F[生成分数明细] + F --> G[生成匹配原因] + G --> H[返回重排序结果] + + style B fill:#e1f5ff + style C fill:#fff9c4 + style H fill:#c8e6c9 +``` + +## 6. 会话管理流程 + +```mermaid +flowchart TD + A[接收消息] --> B{Session ID 存在?} + B -->|是| C[从 Redis 获取 Session] + B -->|否| D[创建新 Session] + C --> E{Session 有效?} + D --> F[保存到 Redis] + E -->|是| G[追加消息到历史] + E -->|否| F + F --> G + G --> H[更新 updated_at] + H --> I[异步保存到 PostgreSQL] + I --> J[处理业务逻辑] + J --> K[返回响应] + + style D fill:#fff9c4 + style F fill:#e3f2fd + style I fill:#e1f5ff + style K fill:#c8e6c9 +``` + +## 7. 技能向量生成流程 + +```mermaid +flowchart TD + A[技能版本发布] --> B[提取技能元数据] + B --> C[构建嵌入文本] + C --> C1[技能名称] + C --> C2[技能描述] + C --> C3[关键词] + C --> C4[使用示例] + C1 --> D[调用 OpenAI Embedding API] + C2 --> D + C3 --> D + C4 --> D + D --> E[接收向量响应] + E --> F[存储到 skill_embedding 表] + F --> G[创建 4 种类型嵌入] + G --> G1[description] + G --> G2[example] + G --> G3[usage] + G --> G4[combined] + G1 --> H[更新向量索引] + G2 --> H + G3 --> H + G4 --> H + H --> I[完成] + + style D fill:#ffebee + style F fill:#e3f2fd + style H fill:#c8e6c9 +``` + +## 8. 错误处理流程 + +```mermaid +flowchart TD + A[执行操作] --> B{成功?} + B -->|是| C[返回结果] + B -->|否| D{错误类型} + D -->|OpenAI API 失败| E[降级到哈希向量] + D -->|向量索引不可用| F[使用全文搜索] + D -->|意图识别失败| G[使用默认意图] + D -->|数据库连接失败| H[返回缓存结果或错误] + D -->|超时| I[返回部分结果] + E --> J[记录降级日志] + F --> J + G --> J + H --> J + I --> J + J --> C + + style E fill:#fff3e0 + style F fill:#fff3e0 + style G fill:#fff3e0 + style H fill:#ffcdd2 + style I fill:#fff3e0 +``` + +## 9. 缓存查询流程 + +```mermaid +flowchart TD + A[接收查询请求] --> B[生成缓存键] + B --> C{缓存命中?} + C -->|是| D[返回缓存结果] + C -->|否| E[执行完整检索] + E --> F[保存到缓存] + F --> G[返回结果] + D --> H{缓存 TTL 过期?} + H -->|是| I[异步刷新缓存] + H -->|否| J[完成] + I --> J + G --> J + + style C fill:#e1f5ff + style D fill:#c8e6c9 + style I fill:#fff9c4 +``` + +## 10. 批量向量更新流程 + +```mermaid +flowchart TD + A[定时任务触发] --> B[查询待更新技能] + B --> C{有待更新技能?} + C -->|否| D[结束] + C -->|是| E[批量获取技能元数据] + E --> F[批量调用 Embedding API
batch_size=100] + F --> G{API 调用成功?} + G -->|是| H[批量更新数据库] + G -->|否| I[记录失败日志
重试队列] + H --> J[更新向量索引] + I --> K{重试次数 < 3?} + K -->|是| F + K -->|否| L[标记为失败] + J --> B + L --> B + D --> M[完成] + + style F fill:#e3f2fd + style H fill:#e3f2fd + style I fill:#fff3e0 + style L fill:#ffcdd2 +``` diff --git a/docs/agent-skills-search/doc-01/06-architecture-diagrams.md b/docs/agent-skills-search/doc-01/06-architecture-diagrams.md new file mode 100644 index 00000000..b4fff248 --- /dev/null +++ b/docs/agent-skills-search/doc-01/06-architecture-diagrams.md @@ -0,0 +1,526 @@ +# Agent Skills 智能检索系统 - 架构图 + +## 1. 系统整体架构 + +```mermaid +graph TB + subgraph "Client Layer" + A[Agent Client] + end + + subgraph "API Gateway" + B[REST API] + C[Authentication] + end + + subgraph "Application Layer" + D[Agent Skill Search Controller] + E[Agent Session Controller] + end + + subgraph "Service Layer" + F[AgentContextBuilder] + G[IntentClassifier] + H[QueryEmbedder] + I[HybridSkillSearchService] + J[SkillReranker] + K[AgentSessionService] + end + + subgraph "Domain Layer" + L[AgentSession] + M[AgentMessage] + N[SkillEmbedding] + O[IntentMapping] + end + + subgraph "Infrastructure Layer" + P[(PostgreSQL
+ pgvector)] + Q[(Redis Cache)] + R[OpenAI Embedding API] + end + + A -->|HTTP/JSON| B + B --> C + C --> D + C --> E + D --> F + D --> I + E --> K + F --> K + F --> G + G --> H + H --> R + G --> O + I --> H + I --> N + I --> J + J --> L + K --> L + K --> M + L --> P + M --> P + N --> P + O --> P + K --> Q + + style A fill:#e1f5ff + style R fill:#ffebee + style P fill:#c8e6c9 + style Q fill:#fff9c4 +``` + +## 2. 数据流架构 + +```mermaid +graph LR + subgraph "Input" + A1[Query Text] + A2[Conversation History] + A3[Scenario Description] + A4[User Role] + end + + subgraph "Processing" + B1[Context Builder] + B2[Intent Classifier] + B3[Query Embedder] + B4[Hybrid Search] + B5[Reranker] + end + + subgraph "Storage" + C1[(PostgreSQL)] + C2[(Redis)] + C3[OpenAI API] + end + + subgraph "Output" + D1[Matched Skills] + D2[Match Reasons] + D3[Confidence Scores] + end + + A1 --> B1 + A2 --> B1 + A3 --> B1 + A4 --> B1 + B1 --> B2 + B1 --> B3 + B2 --> C3 + B3 --> C3 + B2 --> B4 + B3 --> B4 + B4 --> C1 + B4 --> B5 + B5 --> D1 + B5 --> D2 + B5 --> D3 + B1 --> C2 + B2 --> C2 + + style A1 fill:#e1f5ff + style C3 fill:#ffebee + style D1 fill:#c8e6c9 +``` + +## 3. 模块依赖关系 + +```mermaid +graph TD + A[AgentSkillSearchController] --> B[AgentContextBuilder] + A --> C[HybridSkillSearchService] + + B --> D[AgentSessionService] + D --> E[AgentSessionRepository] + E --> F[(PostgreSQL)] + + C --> G[QueryEmbedder] + C --> H[IntentClassifier] + C --> I[SkillReranker] + C --> J[SkillEmbeddingRepository] + + G --> K[OpenAIEmbeddingClient] + K --> L[OpenAI API] + + H --> G + H --> M[IntentMappingRepository] + M --> F + + I --> N[SkillRepository] + I --> O[LabelRepository] + N --> F + O --> F + + J --> F + + D --> P[RedisTemplate] + P --> Q[(Redis)] + + style A fill:#e1f5ff + style L fill:#ffebee + style F fill:#c8e6c9 + style Q fill:#fff9c4 +``` + +## 4. 数据库架构 + +```mermaid +erDiagram + agent_session ||--o{ agent_message : contains + skill ||--o{ skill_embedding : has + skill ||--o{ skill_label : tagged_with + label_definition ||--o{ skill_label : used_in + + agent_session { + bigint id PK + varchar agent_id + varchar user_id FK + varchar session_id UK + text scenario_description + varchar user_role + jsonb metadata + timestamptz started_at + timestamptz updated_at + timestamptz ended_at + } + + agent_message { + bigint id PK + bigint session_id FK + varchar role + text content + varchar intent_label + decimal intent_confidence + vector embedding + jsonb metadata + timestamptz created_at + } + + skill { + bigint id PK + bigint namespace_id FK + varchar slug + varchar display_name + text summary + varchar owner_id + varchar visibility + varchar status + bigint latest_version_id + bigint download_count + int star_count + decimal rating_avg + int rating_count + } + + skill_embedding { + bigint id PK + bigint skill_id FK + bigint skill_version_id FK + varchar embedding_type + vector embedding + jsonb metadata + timestamptz updated_at + } + + skill_label { + bigint id PK + bigint skill_id FK + bigint label_id FK + } + + label_definition { + bigint id PK + varchar name + varchar slug UK + text description + varchar color + int priority + } + + intent_mapping { + bigint id PK + varchar intent_label UK + text description + text[] skill_categories + text[] example_queries + vector embedding + int priority + boolean active + timestamptz created_at + timestamptz updated_at + } +``` + +## 5. 部署架构 + +```mermaid +graph TB + subgraph "Load Balancer" + LB[Nginx / ALB] + end + + subgraph "Application Servers" + APP1[SkillHub App 1] + APP2[SkillHub App 2] + APP3[SkillHub App N] + end + + subgraph "Data Layer" + PG[PostgreSQL
Primary] + PG_REPLICA[PostgreSQL
Read Replica] + REDIS[Redis Cluster] + end + + subgraph "External Services" + OPENAI[OpenAI API] + end + + LB --> APP1 + LB --> APP2 + LB --> APP3 + + APP1 --> PG + APP1 --> PG_REPLICA + APP1 --> REDIS + APP1 --> OPENAI + + APP2 --> PG + APP2 --> PG_REPLICA + APP2 --> REDIS + APP2 --> OPENAI + + APP3 --> PG + APP3 --> PG_REPLICA + APP3 --> REDIS + APP3 --> OPENAI + + PG -.->|Replication| PG_REPLICA + + style LB fill:#e1f5ff + style PG fill:#c8e6c9 + style REDIS fill:#fff9c4 + style OPENAI fill:#ffebee +``` + +## 6. 缓存架构 + +```mermaid +graph LR + subgraph "Application" + A[Service Layer] + end + + subgraph "Cache Layer - Redis" + B1[Session Cache
TTL: 1h] + B2[Query Result Cache
TTL: 5min] + B3[Embedding Cache
TTL: 1h/Permanent] + end + + subgraph "Database" + C[(PostgreSQL)] + end + + A -->|Get| B1 + A -->|Get| B2 + A -->|Get| B3 + + B1 -.->|Miss| C + B2 -.->|Miss| C + B3 -.->|Miss| C + + C -->|Load| B1 + C -->|Load| B2 + C -->|Load| B3 + + A -->|Update| B1 + A -->|Update| B2 + A -->|Update| B3 + + B1 -.->|Write Through| C + B2 -.->|Write Back| C + B3 -.->|Write Through| C + + style A fill:#e1f5ff + style B1 fill:#fff9c4 + style B2 fill:#fff9c4 + style B3 fill:#fff9c4 + style C fill:#c8e6c9 +``` + +## 7. 搜索流程架构 + +```mermaid +graph TB + subgraph "Query Processing" + A[User Query] --> B[Context Builder] + B --> C[Intent Classifier] + C --> D[Query Embedder] + end + + subgraph "Search Pipeline" + D --> E[Vector Search] + E --> F[Intent Filter] + F --> G[Tag Matcher] + G --> H[Permission Filter] + H --> I[Reranker] + end + + subgraph "Data Sources" + J[(Skill Embeddings)] + K[(Intent Mapping)] + L[(Skill Metadata)] + M[(User Permissions)] + end + + subgraph "Result" + I --> N[Ranked Skills] + N --> O[Response Builder] + end + + E --> J + F --> K + G --> L + H --> M + I --> L + + style A fill:#e1f5ff + style J fill:#c8e6c9 + style K fill:#c8e6c9 + style L fill:#c8e6c9 + style M fill:#c8e6c9 + style N fill:#c8e6c9 +``` + +## 8. 安全架构 + +```mermaid +graph TB + subgraph "Client" + A[Agent Client] + end + + subgraph "Security Layer" + B[Authentication
JWT/OAuth2] + C[Authorization
RBAC] + D[Rate Limiting] + end + + subgraph "Application" + E[API Controller] + end + + subgraph "Data Protection" + F[Input Validation] + G[SQL Injection Prevention] + H[Data Encryption] + end + + subgraph "Infrastructure" + I[PostgreSQL] + J[Redis] + end + + A --> B + B --> C + C --> D + D --> E + E --> F + F --> G + G --> H + H --> I + H --> J + + style B fill:#fff9c4 + style C fill:#fff9c4 + style D fill:#fff9c4 + style G fill:#ffebee + style H fill:#ffebee +``` + +## 9. 监控与日志架构 + +```mermaid +graph TB + subgraph "Application" + A[Services] + end + + subgraph "Logging" + B[Structured Logs] + C[Log Aggregation] + end + + subgraph "Metrics" + D[Prometheus] + E[Custom Metrics] + end + + subgraph "Tracing" + F[OpenTelemetry] + G[Jaeger/Tempo] + end + + subgraph "Alerting" + H[Alert Manager] + I[Notifications] + end + + A --> B + A --> E + A --> F + B --> C + E --> D + F --> G + D --> H + C --> H + H --> I + + style A fill:#e1f5ff + style D fill:#c8e6c9 + style G fill:#fff9c4 + style H fill:#ffebee +``` + +## 10. 扩展性架构 + +```mermaid +graph TB + subgraph "Current System" + A[Core Services] + end + + subgraph "Extension Points" + B1[Embedding Provider
Interface] + B2[Intent Classifier
Interface] + B3[Reranking Strategy
Interface] + B4[Filter Plugin
Interface] + end + + subgraph "Possible Extensions" + C1[Local Embedding
Models] + C2[Custom Intent
Classifiers] + C3[Business-specific
Reranking] + C4[Domain Filters] + end + + A --> B1 + A --> B2 + A --> B3 + A --> B4 + + B1 -.->|Implement| C1 + B2 -.->|Implement| C2 + B3 -.->|Implement| C3 + B4 -.->|Implement| C4 + + style A fill:#e1f5ff + style B1 fill:#fff9c4 + style B2 fill:#fff9c4 + style B3 fill:#fff9c4 + style B4 fill:#fff9c4 + style C1 fill:#e8f5e9 + style C2 fill:#e8f5e9 + style C3 fill:#e8f5e9 + style C4 fill:#e8f5e9 +``` diff --git a/docs/agent-skills-search/doc-01/07-api-design.md b/docs/agent-skills-search/doc-01/07-api-design.md new file mode 100644 index 00000000..45bdf4c4 --- /dev/null +++ b/docs/agent-skills-search/doc-01/07-api-design.md @@ -0,0 +1,606 @@ +# Agent Skills 智能检索系统 - API 设计 + +## 1. 概述 + +Agent Skills 智能检索系统提供 RESTful API,支持 Agent 进行智能技能检索和会话管理。 + +## 2. API 基础信息 + +### 2.1 基础 URL + +``` +生产环境: https://api.skillhub.example.com/api/agent +开发环境: http://localhost:8080/api/agent +``` + +### 2.2 认证方式 + +使用 Bearer Token 认证: + +``` +Authorization: Bearer {access_token} +``` + +### 2.3 通用响应格式 + +**成功响应**: +```json +{ + "code": 0, + "message": "success", + "data": { ... }, + "timestamp": "2024-04-05T10:30:00Z" +} +``` + +**错误响应**: +```json +{ + "code": 40001, + "message": "Invalid request parameter", + "details": { + "field": "query", + "error": "Query text cannot be empty" + }, + "timestamp": "2024-04-05T10:30:00Z" +} +``` + +## 3. 会话管理 API + +### 3.1 创建会话 + +**请求**: +``` +POST /api/agent/sessions +``` + +**请求体**: +```json +{ + "agentId": "agent-001", + "userId": "user-123", + "scenarioDescription": "Web 前端开发", + "userRole": "frontend-developer", + "metadata": { + "projectId": "project-456", + "environment": "development" + } +} +``` + +**响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "sessionId": "sess-789-xyz", + "agentId": "agent-001", + "userId": "user-123", + "scenarioDescription": "Web 前端开发", + "userRole": "frontend-developer", + "metadata": { + "projectId": "project-456", + "environment": "development" + }, + "startedAt": "2024-04-05T10:30:00Z", + "updatedAt": "2024-04-05T10:30:00Z" + } +} +``` + +### 3.2 获取会话 + +**请求**: +``` +GET /api/agent/sessions/{sessionId} +``` + +**响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "sessionId": "sess-789-xyz", + "agentId": "agent-001", + "userId": "user-123", + "scenarioDescription": "Web 前端开发", + "userRole": "frontend-developer", + "messageCount": 5, + "startedAt": "2024-04-05T10:30:00Z", + "updatedAt": "2024-04-05T10:35:00Z", + "endedAt": null + } +} +``` + +### 3.3 获取会话历史 + +**请求**: +``` +GET /api/agent/sessions/{sessionId}/messages?limit=10&offset=0 +``` + +**响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "messages": [ + { + "id": 1, + "role": "user", + "content": "我需要一个处理 JSON 数据的技能", + "intentLabel": "data_processing", + "intentConfidence": 0.92, + "createdAt": "2024-04-05T10:30:00Z" + }, + { + "id": 2, + "role": "assistant", + "content": "我为您找到了几个相关技能...", + "createdAt": "2024-04-05T10:30:05Z" + } + ], + "total": 5, + "limit": 10, + "offset": 0 + } +} +``` + +### 3.4 结束会话 + +**请求**: +``` +POST /api/agent/sessions/{sessionId}/end +``` + +**响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "sessionId": "sess-789-xyz", + "endedAt": "2024-04-05T11:00:00Z" + } +} +``` + +## 4. 技能搜索 API + +### 4.1 智能技能搜索 + +**请求**: +``` +POST /api/agent/skills/search +``` + +**请求体**: +```json +{ + "query": "我需要一个处理 JSON 数据的技能", + "sessionId": "sess-789-xyz", + "limit": 10, + "options": { + "enableIntentRecognition": true, + "enableContextAware": true, + "tags": ["json", "data-processing"], + "intent": "data_processing", + "minConfidence": 0.3 + } +} +``` + +**参数说明**: + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| query | string | 是 | 搜索查询文本 | +| sessionId | string | 否 | 会话 ID,用于上下文感知 | +| limit | integer | 否 | 返回结果数量,默认 10 | +| options.enableIntentRecognition | boolean | 否 | 是否启用意图识别,默认 true | +| options.enableContextAware | boolean | 否 | 是否启用上下文感知,默认 true | +| options.tags | string[] | 否 | 指定标签过滤 | +| options.intent | string | 否 | 指定意图(跳过自动识别) | +| options.minConfidence | number | 否 | 最小置信度,默认 0.3 | + +**响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "query": "我需要一个处理 JSON 数据的技能", + "intent": { + "label": "data_processing", + "confidence": 0.92, + "alternatives": [ + { + "label": "file_processing", + "confidence": 0.75 + } + ] + }, + "results": [ + { + "skillId": 123, + "name": "json-parser", + "displayName": "JSON Parser", + "namespace": "default", + "summary": "强大的 JSON 解析和处理库", + "version": "1.2.3", + "scores": { + "vectorSimilarity": 0.89, + "intentMatchScore": 1.0, + "tagMatchScore": 0.8, + "popularityScore": 0.65, + "ratingScore": 0.88, + "finalScore": 0.87 + }, + "matchReason": "高度匹配:查询向量相似度 0.89,意图完全匹配,标签匹配度 80%", + "tags": ["json", "parser", "data"], + "downloadCount": 1520, + "ratingAvg": 4.4, + "ratingCount": 45 + }, + { + "skillId": 456, + "name": "data-transformer", + "displayName": "Data Transformer", + "namespace": "utils", + "summary": "通用数据转换工具", + "version": "2.1.0", + "scores": { + "vectorSimilarity": 0.76, + "intentMatchScore": 1.0, + "tagMatchScore": 0.6, + "popularityScore": 0.45, + "ratingScore": 0.8, + "finalScore": 0.72 + }, + "matchReason": "良好匹配:意图完全匹配,部分标签匹配", + "tags": ["data", "transform"], + "downloadCount": 890, + "ratingAvg": 4.0, + "ratingCount": 28 + } + ], + "total": 45, + "limit": 10, + "processingTimeMs": 245 + } +} +``` + +### 4.2 快速搜索(简化版) + +**请求**: +``` +GET /api/agent/skills/search?q={query}&limit={limit} +``` + +**示例**: +``` +GET /api/agent/skills/search?q=json%20parser&limit=5 +``` + +**响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "query": "json parser", + "results": [ + { + "skillId": 123, + "name": "json-parser", + "displayName": "JSON Parser", + "namespace": "default", + "summary": "强大的 JSON 解析和处理库", + "version": "1.2.3", + "score": 0.87 + } + ] + } +} +``` + +## 5. 意图管理 API + +### 5.1 获取所有意图 + +**请求**: +``` +GET /api/agent/intents?activeOnly=true +``` + +**响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "intents": [ + { + "id": 1, + "label": "code_generation", + "description": "代码生成相关技能", + "skillCategories": ["coding", "development"], + "exampleQueries": [ + "写一个函数", + "生成代码", + "创建类" + ], + "priority": 10, + "active": true + }, + { + "id": 2, + "label": "data_analysis", + "description": "数据分析相关技能", + "skillCategories": ["data", "analysis"], + "exampleQueries": [ + "分析数据", + "绘制图表", + "数据统计" + ], + "priority": 10, + "active": true + } + ] + } +} +``` + +### 5.2 识别意图 + +**请求**: +``` +POST /api/agent/intents/recognize +``` + +**请求体**: +```json +{ + "query": "我需要生成一个处理用户认证的函数" +} +``` + +**响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "primaryIntent": { + "label": "code_generation", + "confidence": 0.88 + }, + "alternativeIntents": [ + { + "label": "authentication", + "confidence": 0.72 + }, + { + "label": "general", + "confidence": 0.15 + } + ], + "processingTimeMs": 85 + } +} +``` + +## 6. 批量操作 API + +### 6.1 批量生成技能嵌入 + +**请求**: +``` +POST /api/agent/skills/embeddings/batch +``` + +**请求体**: +```json +{ + "skillIds": [123, 456, 789], + "embeddingTypes": ["description", "combined"] +} +``` + +**响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "taskId": "task-001-xyz", + "status": "processing", + "totalCount": 3, + "successCount": 0, + "failureCount": 0, + "estimatedCompletion": "2024-04-05T10:35:00Z" + } +} +``` + +### 6.2 查询批量任务状态 + +**请求**: +``` +GET /api/agent/tasks/{taskId} +``` + +**响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "taskId": "task-001-xyz", + "status": "completed", + "totalCount": 3, + "successCount": 3, + "failureCount": 0, + "results": [ + { + "skillId": 123, + "status": "success", + "embeddingTypes": ["description", "combined"] + } + ], + "startedAt": "2024-04-05T10:30:00Z", + "completedAt": "2024-04-05T10:31:15Z" + } +} +``` + +## 7. 错误码 + +| 错误码 | 说明 | HTTP 状态码 | +|--------|------|-------------| +| 0 | 成功 | 200 | +| 40001 | 请求参数错误 | 400 | +| 40002 | 缺少必填参数 | 400 | +| 40101 | 未认证 | 401 | +| 40301 | 无权限访问 | 403 | +| 40401 | 资源不存在 | 404 | +| 40901 | 资源冲突 | 409 | +| 42901 | 请求频率超限 | 429 | +| 50001 | 服务器内部错误 | 500 | +| 50301 | 服务不可用 | 503 | +| 50002 | OpenAI API 调用失败 | 500 | +| 50003 | 向量索引不可用 | 500 | + +## 8. 速率限制 + +| 端点 | 限制 | 时间窗口 | +|------|------|----------| +| POST /api/agent/skills/search | 100 | 1分钟 | +| GET /api/agent/sessions/{id} | 200 | 1分钟 | +| POST /api/agent/sessions | 50 | 1分钟 | +| POST /api/agent/intents/recognize | 60 | 1分钟 | + +**响应头**: +``` +X-RateLimit-Limit: 100 +X-RateLimit-Remaining: 95 +X-RateLimit-Reset: 1712289000 +``` + +## 9. Webhook 通知 + +### 9.1 向量生成完成通知 + +**请求体**: +```json +{ + "eventType": "embedding.completed", + "timestamp": "2024-04-05T10:30:00Z", + "data": { + "skillId": 123, + "skillVersionId": 456, + "embeddingTypes": ["description", "combined"], + "status": "success" + } +} +``` + +## 10. SDK 示例 + +### 10.1 JavaScript/TypeScript + +```typescript +import { SkillHubAgentClient } from '@skillhub/agent-sdk'; + +const client = new SkillHubAgentClient({ + baseURL: 'https://api.skillhub.example.com/api/agent', + apiKey: 'your-api-key' +}); + +// 创建会话 +const session = await client.createSession({ + agentId: 'agent-001', + userId: 'user-123', + scenarioDescription: 'Web 前端开发', + userRole: 'frontend-developer' +}); + +// 搜索技能 +const results = await client.searchSkills({ + query: '我需要一个处理 JSON 数据的技能', + sessionId: session.sessionId, + limit: 10 +}); + +console.log(results.results); +``` + +### 10.2 Python + +```python +from skillhub_agent import SkillHubAgentClient + +client = SkillHubAgentClient( + base_url='https://api.skillhub.example.com/api/agent', + api_key='your-api-key' +) + +# 创建会话 +session = client.create_session( + agent_id='agent-001', + user_id='user-123', + scenario_description='Web 前端开发', + user_role='frontend-developer' +) + +# 搜索技能 +results = client.search_skills( + query='我需要一个处理 JSON 数据的技能', + session_id=session['sessionId'], + limit=10 +) + +print(results['results']) +``` + +### 10.3 Java + +```java +import com.iflytek.skillhub.agent.SkillHubAgentClient; +import com.iflytek.skillhub.agent.dto.*; + +SkillHubAgentClient client = new SkillHubAgentClient( + "https://api.skillhub.example.com/api/agent", + "your-api-key" +); + +// 创建会话 +CreateSessionRequest sessionRequest = CreateSessionRequest.builder() + .agentId("agent-001") + .userId("user-123") + .scenarioDescription("Web 前端开发") + .userRole("frontend-developer") + .build(); + +AgentSession session = client.createSession(sessionRequest); + +// 搜索技能 +SearchSkillsRequest searchRequest = SearchSkillsRequest.builder() + .query("我需要一个处理 JSON 数据的技能") + .sessionId(session.getSessionId()) + .limit(10) + .build(); + +SearchSkillsResponse results = client.searchSkills(searchRequest); + +results.getResults().forEach(skill -> { + System.out.println(skill.getName() + ": " + skill.getFinalScore()); +}); +``` diff --git a/docs/agent-skills-search/doc-01/08-implementation-guide.md b/docs/agent-skills-search/doc-01/08-implementation-guide.md new file mode 100644 index 00000000..37b606c4 --- /dev/null +++ b/docs/agent-skills-search/doc-01/08-implementation-guide.md @@ -0,0 +1,648 @@ +# Agent Skills 智能检索系统 - 实施指南 + +## 1. 实施阶段 + +### 阶段 1:基础设施准备(1-2 周) + +#### 1.1 数据库配置 + +**安装 pgvector 扩展**: + +```bash +# 连接到 PostgreSQL +psql -U postgres -d skillhub + +# 安装 pgvector 扩展 +CREATE EXTENSION IF NOT EXISTS vector; + +# 验证安装 +SELECT * FROM pg_extension WHERE extname = 'vector'; + +# 查看可用版本 +SELECT * FROM pg_available_extensions WHERE name = 'vector'; +``` + +**配置连接池**(application.yml): +```yaml +spring: + datasource: + hikari: + maximum-pool-size: 20 + minimum-idle: 5 + connection-timeout: 30000 + idle-timeout: 600000 + max-lifetime: 1800000 +``` + +#### 1.2 Redis 配置 + +```yaml +spring: + data: + redis: + host: localhost + port: 6379 + password: ${REDIS_PASSWORD} + database: 0 + timeout: 5000ms + lettuce: + pool: + max-active: 20 + max-idle: 10 + min-idle: 5 +``` + +#### 1.3 OpenAI API 配置 + +```yaml +openai: + api-key: ${OPENAI_API_KEY} + embedding: + model: text-embedding-3-small + dimension: 1536 + timeout: 30000 + max-retries: 3 +``` + +### 阶段 2:数据库迁移(1 周) + +#### 2.1 创建迁移脚本 + +创建 `V__create_agent_tables.sql`: + +```sql +-- 参见 03-data-model.md 中的完整 SQL + +-- 1. 安装 pgvector +CREATE EXTENSION IF NOT EXISTS vector; + +-- 2. 创建 agent_session 表 +... + +-- 3. 创建 agent_message 表 +... + +-- 4. 创建 skill_embedding 表 +... + +-- 5. 创建 intent_mapping 表 +... + +-- 6. 创建索引 +... + +-- 7. 插入初始数据 +INSERT INTO intent_mapping (intent_label, description, skill_categories, example_queries, priority, active) +VALUES + ('code_generation', '代码生成相关技能', ARRAY['coding', 'development'], ARRAY['写一个函数', '生成代码', '创建类'], 10, true), + ('data_analysis', '数据分析相关技能', ARRAY['data', 'analysis'], ARRAY['分析数据', '绘制图表', '数据统计'], 10, true), + ... +; +``` + +#### 2.2 执行迁移 + +```bash +# 使用 Flyway +mvn flyway:migrate + +# 或使用 Spring Boot 自动迁移 +mvn spring-boot:run -Dspring.flyway.enabled=true +``` + +### 阶段 3:核心服务开发(2-3 周) + +#### 3.1 领域模型 + +创建 `server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/agent/` 目录: + +```java +// AgentSession.java +@Entity +@Table(name = "agent_session") +public class AgentSession { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "agent_id", nullable = false) + private String agentId; + + @Column(name = "user_id", nullable = false) + private String userId; + + @Column(name = "session_id", nullable = false, unique = true) + private String sessionId; + + // ... 其他字段 + + @PrePersist + protected void onCreate() { + startedAt = Instant.now(); + updatedAt = Instant.now(); + } +} +``` + +#### 3.2 Repository 接口 + +```java +// AgentSessionRepository.java +@Repository +public interface AgentSessionRepository extends JpaRepository { + Optional findBySessionId(String sessionId); + + List findByUserIdAndEndedAtIsNull(String userId); + + @Query("SELECT a FROM AgentSession a WHERE a.sessionId = :sessionId AND a.endedAt IS NULL") + Optional findActiveBySessionId(@Param("sessionId") String sessionId); +} +``` + +#### 3.3 服务实现 + +**AgentContextBuilder.java**: +```java +@Service +public class AgentContextBuilderImpl implements AgentContextBuilder { + + private final AgentSessionService sessionService; + private final int maxHistorySize; + + @Override + public AgentSearchContext build(AgentSearchRequest request) { + // 获取会话历史 + List history = request.sessionId() != null + ? sessionService.getRecentMessages(request.sessionId(), maxHistorySize) + : List.of(); + + return new AgentSearchContext( + request.query(), + history, + request.scenarioDescription(), + request.userRole(), + request.metadata() + ); + } +} +``` + +**IntentClassifier.java**: +```java +@Service +public class VectorIntentClassifier implements IntentClassifier { + + private final IntentMappingRepository intentRepository; + private final OpenAiEmbeddingClient embeddingClient; + private final double minConfidence = 0.3; + + @Override + public IntentClassificationResult classify(String query, AgentSearchContext context) { + // 生成查询向量 + float[] queryVector = embeddingClient.embed(query); + + // 获取所有活跃意图 + List intents = intentRepository.findByActiveTrue(); + + // 计算相似度 + List scores = intents.stream() + .map(intent -> new IntentScore( + intent.getIntentLabel(), + cosineSimilarity(queryVector, parseVector(intent.getEmbedding())) + )) + .sorted(Comparator.comparingDouble(IntentScore::score).reversed()) + .toList(); + + if (scores.isEmpty() || scores.get(0).score() < minConfidence) { + return new IntentClassificationResult("general", 0.0, List.of()); + } + + return new IntentClassificationResult( + scores.get(0).label(), + scores.get(0).score(), + scores.subList(1, Math.min(3, scores.size())) + .stream() + .map(IntentScore::label) + .toList() + ); + } + + private double cosineSimilarity(float[] a, float[] b) { + double dot = 0, normA = 0, normB = 0; + for (int i = 0; i < a.length; i++) { + dot += a[i] * b[i]; + normA += a[i] * a[i]; + normB += b[i] * b[i]; + } + return dot / (Math.sqrt(normA) * Math.sqrt(normB)); + } +} +``` + +#### 3.4 OpenAI 集成 + +**OpenAiEmbeddingClient.java**: +```java +@Service +public class OpenAiEmbeddingClient { + + private final String apiKey; + private final String model; + private final RestTemplate restTemplate; + + public float[] embed(String text) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setBearerAuth(apiKey); + + Map body = Map.of( + "model", model, + "input", text + ); + + HttpEntity> request = new HttpEntity<>(body, headers); + + OpenAiResponse response = restTemplate.postForObject( + "https://api.openai.com/v1/embeddings", + request, + OpenAiResponse.class + ); + + return response.data().get(0).embedding(); + } +} +``` + +### 阶段 4:向量生成(1 周) + +#### 4.1 批量向量生成任务 + +```java +@Service +public class SkillEmbeddingGenerator { + + @Scheduled(fixedDelay = 3600000) // 每小时检查一次 + public void generatePendingEmbeddings() { + List skills = skillRepository.findSkillsWithoutEmbeddings(); + + for (Skill skill : skills) { + try { + generateEmbeddings(skill); + } catch (Exception e) { + log.error("Failed to generate embeddings for skill {}", skill.getId(), e); + } + } + } + + private void generateEmbeddings(Skill skill) { + String description = skill.getSummary() != null ? skill.getSummary() : ""; + float[] descVector = embeddingClient.embed(description); + + SkillEmbedding embedding = new SkillEmbedding(); + embedding.setSkillId(skill.getId()); + embedding.setEmbeddingType(EmbeddingType.DESCRIPTION); + embedding.setEmbedding(serializeVector(descVector)); + embedding.setUpdatedAt(Instant.now()); + + embeddingRepository.save(embedding); + } +} +``` + +#### 4.2 手动触发向量生成 + +```java +@RestController +@RequestMapping("/api/admin/skills") +public class AdminSkillController { + + @PostMapping("/{skillId}/embeddings") + public ResponseEntity generateEmbeddings(@PathVariable Long skillId) { + Skill skill = skillRepository.findById(skillId) + .orElseThrow(() -> new NotFoundException("Skill not found")); + + embeddingGenerator.generateEmbeddings(skill); + + return ResponseEntity.ok(Map.of("status", "processing")); + } +} +``` + +### 阶段 5:API 开发(1 周) + +#### 5.1 Controller 实现 + +**AgentSkillSearchController.java**: +```java +@RestController +@RequestMapping("/api/agent") +@RequiredArgsConstructor +public class AgentSkillSearchController { + + private final HybridSkillSearchService searchService; + + @PostMapping("/skills/search") + public ResponseEntity> searchSkills( + @Valid @RequestBody AgentSearchRequest request + ) { + SearchResult result = searchService.search(request); + return ResponseEntity.ok(ApiResponse.success(result)); + } + + @PostMapping("/sessions") + public ResponseEntity> createSession( + @Valid @RequestBody CreateSessionRequest request + ) { + AgentSession session = sessionService.createSession(request); + return ResponseEntity.ok(ApiResponse.success(session)); + } +} +``` + +#### 5.2 DTO 定义 + +```java +public record AgentSearchRequest( + @NotBlank String query, + String sessionId, + @Min(1) @Max(100) Integer limit, + SearchOptions options +) { + public AgentSearchRequest { + if (limit == null) limit = 10; + if (options == null) options = new SearchOptions(); + } +} + +public record SearchOptions( + Boolean enableIntentRecognition, + Boolean enableContextAware, + List tags, + String intent, + Double minConfidence +) { + public SearchOptions { + if (enableIntentRecognition == null) enableIntentRecognition = true; + if (enableContextAware == null) enableContextAware = true; + if (minConfidence == null) minConfidence = 0.3; + } +} +``` + +### 阶段 6:测试(1-2 周) + +#### 6.1 单元测试 + +```java +@SpringBootTest +class IntentClassifierTest { + + @Autowired + private IntentClassifier intentClassifier; + + @Test + void testClassifyCodeGenerationIntent() { + String query = "写一个快速排序算法"; + + IntentClassificationResult result = intentClassifier.classify(query, null); + + assertEquals("code_generation", result.intentLabel()); + assertTrue(result.confidence() > 0.5); + } +} +``` + +#### 6.2 集成测试 + +```java +@SpringBootTest +@AutoConfigureMockMvc +class AgentSkillSearchIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void testSearchSkillsEndpoint() throws Exception { + String request = """ + { + "query": "处理 JSON 数据", + "sessionId": "test-session-123", + "limit": 5 + } + """; + + mockMvc.perform(post("/api/agent/skills/search") + .contentType(MediaType.APPLICATION_JSON) + .content(request)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)) + .andExpect(jsonPath("$.data.results").isArray()); + } +} +``` + +### 阶段 7:部署(1 周) + +#### 7.1 Docker 配置 + +**Dockerfile**: +```dockerfile +FROM openjdk:21-slim + +WORKDIR /app + +COPY target/skillhub-app.jar /app/ + +EXPOSE 8080 + +ENTRYPOINT ["java", "-jar", "skillhub-app.jar"] +``` + +#### 7.2 Kubernetes 配置 + +**deployment.yaml**: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: skillhub-agent +spec: + replicas: 3 + selector: + matchLabels: + app: skillhub-agent + template: + metadata: + labels: + app: skillhub-agent + spec: + containers: + - name: skillhub + image: skillhub/agent:latest + ports: + - containerPort: 8080 + env: + - name: SPRING_DATASOURCE_URL + valueFrom: + secretKeyRef: + name: skillhub-secrets + key: database-url + - name: OPENAI_API_KEY + valueFrom: + secretKeyRef: + name: skillhub-secrets + key: openai-api-key + resources: + requests: + memory: "512Mi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "1000m" +``` + +### 阶段 8:监控与调优(持续) + +#### 8.1 监控指标 + +```java +@Component +public class SearchMetrics { + + private final MeterRegistry meterRegistry; + + public void recordSearch(SearchResult result, long duration) { + meterRegistry.counter("skill.search.total", + "intent", result.intent().label() + ).increment(); + + meterRegistry.timer("skill.search.duration").record(duration, TimeUnit.MILLISECONDS); + + result.results().forEach(r -> + meterRegistry.histogram("skill.search.score").record(r.finalScore()) + ); + } +} +``` + +#### 8.2 性能调优 + +**向量索引调优**: +```sql +-- 根据数据量调整 lists 参数 +-- 建议值:sqrt(行数) +CREATE INDEX idx_skill_embedding_embedding ON skill_embedding + USING ivfflat(embedding vector_cosine_ops) + WITH (lists = 100); +``` + +**缓存配置优化**: +```yaml +skillhub: + agent: + search: + cache: + enabled: true + ttl: 300 # 5分钟 + max-size: 10000 +``` + +## 9. 检查清单 + +### 准备阶段 +- [ ] PostgreSQL 17 安装完成 +- [ ] pgvector 扩展安装完成 +- [ ] Redis 7.0 配置完成 +- [ ] OpenAI API Key 获取 +- [ ] 数据库迁移脚本准备 + +### 开发阶段 +- [ ] 领域模型定义完成 +- [ ] Repository 接口定义完成 +- [ ] 核心服务实现完成 +- [ ] OpenAI 集成完成 +- [ ] 混合检索实现完成 +- [ ] API 端点实现完成 + +### 测试阶段 +- [ ] 单元测试覆盖率 > 80% +- [ ] 集成测试通过 +- [ ] 性能测试达标(< 500ms) +- [ ] 负载测试通过(100+ QPS) + +### 部署阶段 +- [ ] Docker 镜像构建完成 +- [ ] Kubernetes 配置完成 +- [ ] 环境变量配置完成 +- [ ] 健康检查配置完成 +- [ ] 日志收集配置完成 + +### 上线后 +- [ ] 监控指标配置完成 +- [ ] 告警规则配置完成 +- [ ] 文档更新完成 +- [ ] 团队培训完成 + +## 10. 常见问题 + +### Q1: pgvector 索引创建失败 + +**原因**:数据量不足或参数不当 + +**解决**: +```sql +-- 确保有足够的数据(至少 100 行) +-- 调整 lists 参数 +CREATE INDEX idx_skill_embedding_embedding ON skill_embedding + USING ivfflat(embedding vector_cosine_ops) + WITH (lists = 32); +``` + +### Q2: OpenAI API 调用超时 + +**原因**:网络延迟或 API 限制 + +**解决**: +```yaml +openai: + embedding: + timeout: 60000 # 增加超时时间 + max-retries: 5 # 增加重试次数 +``` + +### Q3: 搜索结果不准确 + +**原因**:向量未生成或权重配置不当 + +**解决**: +1. 检查技能向量是否生成 +2. 调整重排序权重 +3. 增加意图类别和示例 + +### Q4: 内存占用过高 + +**原因**:向量数据量大,缓存过多 + +**解决**: +```yaml +spring: + jpa: + properties: + hibernate: + jdbc: + batch_size: 50 + +skillhub: + agent: + search: + cache: + max-size: 5000 # 减少缓存大小 +``` + +## 11. 参考资源 + +- [pgvector 官方文档](https://github.com/pgvector/pgvector) +- [OpenAI Embeddings API](https://platform.openai.com/docs/guides/embeddings) +- [Spring Boot 文档](https://spring.io/projects/spring-boot) +- [PostgreSQL 性能调优](https://wiki.postgresql.org/wiki/Performance_Optimization) diff --git a/docs/sso-build-ceph/ceph-migration-plan.md b/docs/sso-build-ceph/ceph-migration-plan.md new file mode 100644 index 00000000..92b8acfb --- /dev/null +++ b/docs/sso-build-ceph/ceph-migration-plan.md @@ -0,0 +1,231 @@ +# MinIO 迁移到 Ceph 方案 + +## 背景 + +当前项目使用 MinIO 作为 S3 兼容对象存储,现需迁移到已部署的 Ceph RGW。由于测试环境暂无生产数据,无需数据迁移,直接配置切换即可。 + +## 关键发现 + +**代码层面无需修改**: +- 项目已有 `ObjectStorageService` 抽象接口 +- `S3StorageService` 使用 AWS S3 SDK v2,完全兼容 Ceph RGW +- 通过 `@ConditionalOnProperty(name = "skillhub.storage.provider")` 条件装配 + +## 改动点 + +### 1. K8s ConfigMap 配置 + +**文件**: `deploy/k8s/base/configmap.yaml` + +```yaml +# 修改存储提供商 +skillhub-storage-provider: s3 # 原值: local + +# 添加 Ceph S3 配置 +skillhub-storage-s3-endpoint: http://ceph-rgw:7480 +skillhub-storage-s3-public-endpoint: https://ceph.example.com:7480 +skillhub-storage-s3-bucket: skillhub +skillhub-storage-s3-region: default +skillhub-storage-s3-force-path-style: "true" +skillhub-storage-s3-auto-create-bucket: "true" +skillhub-storage-s3-presign-expiry: PT10M +``` + +**移除本地存储配置**(可选): +```yaml +# 注释或删除 +# storage-base-path: /var/lib/skillhub/storage +``` + +### 2. K8s Secret 配置 + +**文件**: `deploy/k8s/base/secret.yaml.example` + +```yaml +# 添加 Ceph 凭证 +skillhub-storage-s3-access-key: your-ceph-access-key +skillhub-storage-s3-secret-key: your-ceph-secret-key +``` + +创建实际 Secret: +```bash +kubectl create secret generic skillhub-secret \ + --from-literal=skillhub-storage-s3-access-key=your-access-key \ + --from-literal=skillhub-storage-s3-secret-key=your-secret-key \ + --dry-run=client -o yaml | kubectl apply -f - +``` + +### 3. Backend Deployment 配置 + +**文件**: `deploy/k8s/base/backend-deployment.yaml` + +**添加 S3 环境变量**(在 env 部分添加): +```yaml +# Storage - S3 +- name: SKILLHUB_STORAGE_S3_ENDPOINT + valueFrom: + configMapKeyRef: + name: skillhub-config + key: skillhub-storage-s3-endpoint +- name: SKILLHUB_STORAGE_S3_PUBLIC_ENDPOINT + valueFrom: + configMapKeyRef: + name: skillhub-config + key: skillhub-storage-s3-public-endpoint +- name: SKILLHUB_STORAGE_S3_BUCKET + valueFrom: + configMapKeyRef: + name: skillhub-config + key: skillhub-storage-s3-bucket +- name: SKILLHUB_STORAGE_S3_ACCESS_KEY + valueFrom: + secretKeyRef: + name: skillhub-secret + key: skillhub-storage-s3-access-key +- name: SKILLHUB_STORAGE_S3_SECRET_KEY + valueFrom: + secretKeyRef: + name: skillhub-secret + key: skillhub-storage-s3-secret-key +- name: SKILLHUB_STORAGE_S3_REGION + valueFrom: + configMapKeyRef: + name: skillhub-config + key: skillhub-storage-s3-region +- name: SKILLHUB_STORAGE_S3_FORCE_PATH_STYLE + valueFrom: + configMapKeyRef: + name: skillhub-config + key: skillhub-storage-s3-force-path-style +- name: SKILLHUB_STORAGE_S3_AUTO_CREATE_BUCKET + valueFrom: + configMapKeyRef: + name: skillhub-config + key: skillhub-storage-s3-auto-create-bucket +- name: SKILLHUB_STORAGE_S3_PRESIGN_EXPIRY + valueFrom: + configMapKeyRef: + name: skillhub-config + key: skillhub-storage-s3-presign-expiry +``` + +**移除本地存储挂载**(可选): +```yaml +# 注释或删除 volumeMounts 中的 skillhub-storage +# 注释或删除 volumes 中的 skillhub-storage-pvc +``` + +### 4. Docker Compose 配置 + +**文件**: `docker-compose.yml` + +**移除 MinIO 服务**: +```yaml +# minio: +# image: minio/minio:RELEASE.2025-09-07T16-13-09Z +# ports: +# - "9000:9000" +# - "9001:9001" +# ... +``` + +### 5. ConfigMap 中移除 PVC 定义 + +**文件**: `deploy/k8s/base/configmap.yaml` + +```yaml +# 注释或删除 PersistentVolumeClaim 部分 +# --- +# apiVersion: v1 +# kind: PersistentVolumeClaim +# metadata: +# name: skillhub-storage-pvc +# ... +``` + +## 执行步骤 + +1. **更新 ConfigMap** + ```bash + kubectl apply -f deploy/k8s/base/configmap.yaml + ``` + +2. **创建/更新 Secret** + ```bash + kubectl create secret generic skillhub-secret \ + --from-literal=skillhub-storage-s3-access-key= \ + --from-literal=skillhub-storage-s3-secret-key= \ + --dry-run=client -o yaml | kubectl apply -f - + ``` + +3. **更新 Deployment** + ```bash + kubectl apply -f deploy/k8s/base/backend-deployment.yaml + ``` + +4. **重启 Pod** + ```bash + kubectl rollout restart deployment/skillhub-server + ``` + +5. **验证配置** + ```bash + kubectl logs -f deployment/skillhub-server + ``` + +## 验证测试 + +### 功能验证清单 +- [ ] Pod 正常启动,无错误日志 +- [ ] 上传技能包 +- [ ] 下载技能包 +- [ ] 生成预签名 URL +- [ ] 删除技能包 + +### 验证命令 +```bash +# 检查 Pod 日志 +kubectl logs deployment/skillhub-server + +# 检查环境变量 +kubectl exec deployment/skillhub-server -- env | grep STORAGE + +# 测试上传(通过 API) +curl -X POST http:///api/skills/{namespace}/publish \ + -F "file=@test.zip" \ + -F "visibility=public" +``` + +## 关键文件清单 + +| 文件路径 | 操作 | +|---------|------| +| `deploy/k8s/base/configmap.yaml` | 修改:添加 S3 配置 | +| `deploy/k8s/base/secret.yaml.example` | 修改:添加 S3 凭证模板 | +| `deploy/k8s/base/backend-deployment.yaml` | 修改:添加 S3 环境变量 | +| `docker-compose.yml` | 修改:移除 MinIO 服务 | + +## 注意事项 + +1. **Ceph 网络连通性**:确保集群能访问 Ceph RGW 的 endpoint +2. **Bucket 创建**:建议提前创建 bucket,或启用 `auto-create-bucket` +3. **Region 配置**:Ceph 通常使用 `default` region +4. **Path Style**:Ceph RGW 需要启用 `force-path-style` +5. **SSL/TLS**:生产环境建议使用 HTTPS + +## 回滚方案 + +如果出现问题,快速回滚: + +```bash +# 1. 恢复 ConfigMap +git checkout deploy/k8s/base/configmap.yaml +kubectl apply -f deploy/k8s/base/configmap.yaml + +# 2. 恢复 Deployment +git checkout deploy/k8s/base/backend-deployment.yaml +kubectl apply -f deploy/k8s/base/backend-deployment.yaml + +# 3. 重启服务 +kubectl rollout restart deployment/skillhub-server +``` diff --git a/scanner/Dockerfile b/scanner/Dockerfile index 9a50a618..7c349ae9 100644 --- a/scanner/Dockerfile +++ b/scanner/Dockerfile @@ -65,4 +65,4 @@ EXPOSE 8000 HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:8000/health || exit 1 -CMD ["skill-scanner-api", "--host", "0.0.0.0", "--port", "8000"] +CMD ["skill-scanner-api", "--host", "0.0.0.0", "--port", "8000", "--root-path", "/skillhub"] diff --git a/scanner/Dockerfile.debug b/scanner/Dockerfile.debug index d29156e4..2d50dfd3 100644 --- a/scanner/Dockerfile.debug +++ b/scanner/Dockerfile.debug @@ -39,4 +39,4 @@ RUN mkdir -p /tmp/skillhub-scans EXPOSE 8000 -CMD ["skill-scanner-api", "--host", "0.0.0.0", "--port", "8000"] +CMD ["skill-scanner-api", "--host", "0.0.0.0", "--port", "8000", "--root-path", "/skillhub"] diff --git a/scanner/Dockerfile.fallback b/scanner/Dockerfile.fallback index 88fa94a6..158994d2 100644 --- a/scanner/Dockerfile.fallback +++ b/scanner/Dockerfile.fallback @@ -63,4 +63,4 @@ EXPOSE 8000 HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:8000/health || exit 1 -CMD ["skill-scanner-api", "--host", "0.0.0.0", "--port", "8000"] +CMD ["skill-scanner-api", "--host", "0.0.0.0", "--port", "8000", "--root-path", "/skillhub"] diff --git a/scanner/Dockerfile.official b/scanner/Dockerfile.official index 63a2e1ad..1d479778 100644 --- a/scanner/Dockerfile.official +++ b/scanner/Dockerfile.official @@ -45,4 +45,4 @@ EXPOSE 8000 HEALTHCHECK --interval=10s --timeout=3s \ CMD wget -qO- http://127.0.0.1:8000/health || exit 1 -CMD ["skill-scanner-api", "--host", "0.0.0.0", "--port", "8000"] +CMD ["skill-scanner-api", "--host", "0.0.0.0", "--port", "8000", "--root-path", "/skillhub"] diff --git a/scanner/Dockerfile.official-pypi b/scanner/Dockerfile.official-pypi index 24f50589..d7650e13 100644 --- a/scanner/Dockerfile.official-pypi +++ b/scanner/Dockerfile.official-pypi @@ -46,4 +46,4 @@ EXPOSE 8000 HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:8000/health || exit 1 -CMD ["skill-scanner-api", "--host", "0.0.0.0", "--port", "8000"] +CMD ["skill-scanner-api", "--host", "0.0.0.0", "--port", "8000", "--root-path", "/skillhub"] diff --git a/server/skillhub-app/src/main/resources/application-local.yml b/server/skillhub-app/src/main/resources/application-local.yml index 87dd2419..17da557d 100644 --- a/server/skillhub-app/src/main/resources/application-local.yml +++ b/server/skillhub-app/src/main/resources/application-local.yml @@ -3,6 +3,10 @@ spring: hibernate: ddl-auto: validate show-sql: true + properties: + hibernate: + format_sql: true + use_sql_comments: true flyway: enabled: true datasource: @@ -51,3 +55,5 @@ logging: level: com.iflytek.skillhub: INFO org.springframework.security: WARN + org.hibernate.SQL: DEBUG + org.hibernate.type.descriptor.sql.BasicBinder: TRACE