feat(skills,knowledge): 中文名补全与知识库沉淀支持可选大模型并明确大模型报错

技能中文名:
- 单个「AI 生成」与「一键补充中文名」均可在请求体 model_name 选择大模型
- 一键补充改为仅管理员开放
- _generate_skill_name_zh 在模型自身失败(构建/超时/API 报错)时抛
  SkillNameZhModelError,与模型返回无效名称区分;单个接口返回
  502「大模型报错,无法补全技能中文名」,批量在 model_error 中带回代表性报错

知识库沉淀:
- 对话保存到知识库 / 批量导入均新增可选 model_name(透传至 capture_thread
  → extract_thread_llm_multi)
- 批量返回 llm_fallback 计数;模型异常时仍按既有逻辑回退规则抽取并落草稿,
  前端明确提示「已改用规则抽取」(保存按钮保持后台异步)

前端新增 components/workspace/model-name-select.tsx 复用下拉(默认=系统配置模型)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
吉鑫升andClaude Opus 4.8 committed 2026-06-10 11:23:01 +08:00
1 parent 8fbbfc8093
commit 96e0d695c0
11 files changed
+295 -83

No files matched your search

+23 -3
View File
@@ -37,6 +37,7 @@ import {
SelectValue,
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { ModelNameSelect } from "@/components/workspace/model-name-select";
import {
useKnowledgeActions,
useKnowledgeDuplicates,
@@ -241,6 +242,8 @@ function BatchImportDialog({
const { batchIngest } = useKnowledgeActions();
const [limit, setLimit] = useState(50);
const [skipExisting, setSkipExisting] = useState(true);
// Optional model override for extraction (null = configured default).
const [model, setModel] = useState<string | null>(null);
const handleRun = async () => {
try {
@@ -249,10 +252,18 @@ function BatchImportDialog({
skip_existing: skipExisting,
status: "approved",
include_sources: true,
model_name: model,
});
toast.success(
`批量导入完成:新增 ${result.created},跳过 ${result.skipped},失败 ${result.failed}`,
);
const base = `批量导入完成:新增 ${result.created},跳过 ${result.skipped},失败 ${result.failed}`;
if (result.llm_fallback && result.llm_fallback > 0) {
// The model failed on some threads — they were saved via rule-based
// extraction instead. Say so explicitly per the requirement.
toast.warning(
`${base};其中 ${result.llm_fallback} 条因大模型异常改用了规则抽取(草稿)`,
);
} else {
toast.success(base);
}
onOpenChange(false);
} catch (error) {
toast.error(error instanceof Error ? error.message : "批量导入失败");
@@ -289,6 +300,15 @@ function BatchImportDialog({
className="size-4"
/>
</label>
<label className="flex items-center justify-between gap-2 text-sm">
提炼大模型
<ModelNameSelect
value={model}
onChange={setModel}
disabled={batchIngest.isPending}
triggerClassName="h-9 w-[11rem]"
/>
</label>
</div>
<DialogFooter>
<Button variant="outline" onClick={() => onOpenChange(false)}>