import { useEffect, useMemo, useState } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Settings2 } from "lucide-react"; import { modelRoutingApi, type ModelRoutingItem } from "@/api/modelRouting"; import { ConfigSubpageHeader } from "@/components/ai-config/ConfigSubpageHeader"; import { FeatureIntroGuide } from "@/components/ai-config/FeatureIntroGuide"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { formatBeijingDateTime } from "@/lib/datetime"; import { toZhRoutingSource, toZhTierAlias } from "@/lib/display"; const TIER_OPTIONS = ["low", "high"] as const; const FUNCTION_USAGE_DESCRIPTIONS: Record = { adaptive_rag_answer_deep: "复杂问题的深度回答阶段:会做更细的推理和更完整的结论组织。", adaptive_rag_answer_normal: "常规问答阶段:基于已检索到的信息快速生成可读回复。", feishu_humanized_reply: "对外回复润色阶段:把结果改写成飞书里更自然、易读的表达。", rag_db_project_semantic_retrieval: "知识检索阶段:从项目库里找最相关的历史上下文与证据。", rag_intent_classification: "意图识别阶段:先判断这是哪类问题,再决定后续处理路径。", signal_planner_analyze: "任务规划阶段:把需求拆成可执行步骤、产物和责任边界。", classify_intent_ai_pmo_kernel: "轻量意图分流:快速判断是否进入 PMO 内核处理链路。", classify_intent_complex: "复杂意图判别:识别高复杂度请求,决定是否升级到高层模型。", }; function getFunctionUsageHint(functionName: string): string { return FUNCTION_USAGE_DESCRIPTIONS[functionName] || "通用路由节点:用于该函数调用阶段的高低层选择。"; } function describeLastExecution(item: ModelRoutingItem): string { const last = item.last_execution; if (!last) return "暂无执行记录"; return `${last.planned_tier} -> ${last.executed_tier}`; } function describeUpgrade(item: ModelRoutingItem): string { const last = item.last_execution; if (!last) return "-"; return last.planned_tier !== last.executed_tier ? "是" : "否"; } export default function ModelRoutingConfigPage() { const queryClient = useQueryClient(); const [selectedFunction, setSelectedFunction] = useState("signal_planner_analyze"); const [tierAlias, setTierAlias] = useState<(typeof TIER_OPTIONS)[number]>("high"); const routingQuery = useQuery({ queryKey: ["model-routing-functions"], queryFn: () => modelRoutingApi.listFunctions(), }); const items = routingQuery.data || []; const current = useMemo( () => items.find((item) => item.function_name === selectedFunction) || null, [items, selectedFunction] ); useEffect(() => { const fallback: ModelRoutingItem | null = current || items[0] || null; if (!fallback) return; if (!current && fallback.function_name) { setSelectedFunction(fallback.function_name); } const nextTier = TIER_OPTIONS.includes(fallback.tier_alias as (typeof TIER_OPTIONS)[number]) ? (fallback.tier_alias as (typeof TIER_OPTIONS)[number]) : "high"; setTierAlias(nextTier); }, [current, items]); const updateMutation = useMutation({ mutationFn: () => modelRoutingApi.updateFunction(selectedFunction, { tier_alias: tierAlias, }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["model-routing-functions"] }); }, }); const routingErrorText = routingQuery.error instanceof Error ? routingQuery.error.message : "请检查后端服务。"; return (
} tone="blue" meta={{routingQuery.isError ? "读取失败" : `已加载 ${items.length} 条路由`}} />
编辑器 选择函数并更新逻辑 tier。 setSelectedFunction(e.target.value.trim())} placeholder="function_name" />

{getFunctionUsageHint(selectedFunction)}

真实 provider / model 只存在于配置真源,不在调用视图直接展示。
{updateMutation.isError ? (

保存失败:{updateMutation.error instanceof Error ? updateMutation.error.message : "请重试"}

) : null}
生效路由 选中行即当前编辑目标。 {routingQuery.isLoading ? (

加载中...

) : routingQuery.isError ? (

路由读取失败:{routingErrorText}

) : items.length === 0 ? (

暂无路由配置。

) : (
函数 逻辑层 配置来源 规则 最近执行 升级 操作 {items.map((item) => (
{item.function_name}
{getFunctionUsageHint(item.function_name)}
{toZhTierAlias(item.tier_alias)} {toZhRoutingSource(item.source)}
{item.rule_name || "来自配置真源"}
{typeof item.rule_priority === "number" ? `priority ${item.rule_priority}` : "tier default"}
{describeLastExecution(item)}
{item.last_execution?.created_at ? formatBeijingDateTime(item.last_execution.created_at) : "-"}
{describeUpgrade(item)}
))}
)}
); }