Files
pj0235-eai_agentplatform/eai_agentplatform/backend-go/internal/api/helpers.go
T
eaiadminandClaude Code 8b136d4a10 feat: 专员岗位说明书与技能绑定打通(SY23 P0–P4)
工作台对话此前根本不读专员表:smart_assistant.go 里两条写死的 prompt,
专员表零参与,所以「选哪个专员说话都一样」。本次把
「专员 → 岗位说明书 → 技能」接进 system prompt。

P0 修 bug
  batch/extract 与 contract/review 直接把 nil 当路由传给 AI 层,
  取 primary.RouteID 时空指针,这两个接口必 500。
  llm.go 抽出 buildRouteChain,nil 主路由改为显式报错。

P1 数据层
  specialist 表加 rule_file_markdown(岗位说明书正文)与 allowed_skills
  (绑定技能,顺序即优先级)。写入侧用 model.ValidSkillKeys 校验,
  非法 key / 重复项直接 400,并规范化成紧凑 JSON 落库。
  播种 11 份岗位说明书初稿与技能绑定,沿用「存在则只补空字段」,
  管理员改过的内容不会被重启覆盖。

P2 打通链路
  请求体加 task_id 与 specialist_key。后端按任务反查专员(专员是任务的
  字段,任务优先),查不到安静退回通用助手而不是报错打断对话。
  ai_call_log 加 specialist_key,用来回答「这条回答是谁说的」。

P3 注入 prompt
  system prompt 改为 基础角色 + 【当前专员】+【可用技能】+【岗位说明书】,
  说明书放最后(离用户消息最近,优先级最高)。选了专员就不再自称
  「通用助手」——身份冲突正是老毛病的成因。

P4 前端
  对话带上当前任务与专员;专员详情页显示绑定的技能、读哪些信源、
  可以动什么。

验证
  go build / go vet / go test 全绿,45 项测试通过;前端构建通过。
  另在开发库副本上验过真实升级路径(AutoMigrate 补三列 + 播种补齐
  11 个专员),源库未被改动。
  新增防漂移测试:后端技能清单与前端 availableSkills 不一致即红灯;
  专员改名而说明书没同步也会红灯(这类静默失效最难查)。

注:llm.go / credits.go / seed.go / smart_assistant.go / api/specialist.go
同时含有并行进行中的改动(路由健康上报、清理调试埋点、技能与动作种子),
与本方案交织在同一批行内,无法单独拆出,一并随本次提交。

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-17 21:32:31 +08:00

39 lines
1.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package api
import (
"fmt"
"strconv"
"github.com/gin-gonic/gin"
"eai_agentplatform/backend/internal/ai"
"eai_agentplatform/backend/internal/config"
"eai_agentplatform/backend/internal/web"
)
// parseID 解析路径中的 uint id,失败返回 false 并已写入错误响应
func parseID(c *gin.Context, name string) (uint, bool) {
id, err := strconv.ParseUint(c.Param(name), 10, 64)
if err != nil || id == 0 {
web.Fail(c, web.NewBadRequest("无效的 "+name))
return 0, false
}
return uint(id), true
}
// generateWithDefaultRoute 取通用文本生成路由后调用 LLM(非流式 + 回退链)。
//
// 用于请求体里没有 ai_route_id、服务端自行挑路由的场景。路由名沿用代码里既有惯例
// "title_gen"(agent_routes 里指向通用 chat 模型);GetRoute 本身在查不到时会回落到
// ai_config.json 的 default_route,所以这里只可能在配置整体不可用时失败。
//
// 存在的意义:取代此前 ai.GenerateWithFallback(nil, …) 的写法。传 nil 会让
// ai.buildRouteChain 直接报错——历史上前者会让调用方必 500。
func generateWithDefaultRoute(messages []ai.Message) (string, error) {
aiRoute, err := config.GetRoute("title_gen")
if err != nil || aiRoute == nil {
return "", fmt.Errorf("通用文本生成路由不可用: %w", err)
}
return ai.GenerateWithFallback(aiRoute, messages)
}