Files
Fulfilled-Knowledge/wishfulfilled-dashboard/assets/RagAssistant-BEmyfNge.js
2026-05-29 14:33:56 +08:00

5 lines
12 KiB
JavaScript
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.
import{a,j as e}from"./react-vendor-BVoutfaX.js";import{u as O}from"./index-C3mrB48A.js";import"./xyflow-CYMCcsWN.js";import"./graph-layout-7tFr_anw.js";import"./elk-CXeXGyKz.js";import"./graphology-BgTy_cc3.js";const A="ua-rag-llm-settings-v2";function L(){if(typeof window>"u")return{enabled:!1,provider:"auto",endpoint:"http://localhost:11434/v1",model:"qwen2.5:7b",apiKey:""};try{const n=window.localStorage.getItem(A);if(n)return{enabled:!1,provider:"auto",endpoint:"http://localhost:11434/v1",model:"qwen2.5:7b",apiKey:"",...JSON.parse(n)}}catch{}return{enabled:!1,provider:"auto",endpoint:"http://localhost:11434/v1",model:"qwen2.5:7b",apiKey:""}}function Q(n){typeof window>"u"||window.localStorage.setItem(A,JSON.stringify(n))}function G(n){switch(n){case"search":return"本地检索中";case"evidence_rejected":return"证据不足,未调用模型";case"local_answer":return"本地回答";case"llm_done":return"模型回答完成";case"llm_failed":return"模型调用失败";default:return n||"待请求"}}async function q(n,o){const f=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)}),i=await f.text();let b;try{b=i?JSON.parse(i):{}}catch{b={ok:!1,error:{message:i||"响应不是 JSON"}}}return{status:f.status,data:b}}function ee({onClose:n}){const o=O(t=>t.graph),f=O(t=>t.navigateToNodeInLayer),[i,b]=a.useState(""),[v,D]=a.useState(""),[x,w]=a.useState("search"),[d,R]=a.useState(L),[S,h]=a.useState(""),[k,C]=a.useState([]),[j,T]=a.useState(null),[l,c]=a.useState({}),[_,I]=a.useState(!1),[M,E]=a.useState(!1),[K,p]=a.useState(null),[y,N]=a.useState(!1),[u,$]=a.useState(null),z=(o==null?void 0:o.nodes.length)??0,F=a.useMemo(()=>(o==null?void 0:o.nodes.filter(t=>t.id.startsWith("doc:")).length)??0,[o]),g=t=>{const r={...d,...t};R(r),Q(r)},P=async()=>{var r;const t=i.trim();if(D(t),p(null),h(""),C([]),$(null),T(null),c({stage:"search",startedAt:new Date().toISOString()}),!t){h("请输入要检索或提问的内容。");return}I(!0);try{const s=x==="llm"?"/api/rag/answer":"/api/rag/search",{status:B,data:m}=await q(s,{query:t,topK:16,llm:d});if(c(m.requestStatus||{stage:x==="llm"?"llm_done":"local_answer"}),T(m.decision||null),C(m.hits||[]),h(m.answer||"暂无该需求描述。"),!m.ok){const H=((r=m.error)==null?void 0:r.message)||`请求失败HTTP ${B}`;p(H)}}catch(s){p(s instanceof Error?s.message:String(s)),c({stage:"llm_failed"}),h("请求失败,未能获取检索结果。")}finally{I(!1)}},J=async()=>{var t;E(!0),p(null),c({stage:"模型连接测试中",startedAt:new Date().toISOString()});try{const{status:r,data:s}=await q("/api/llm/test",d);s.ok?(c({stage:"llm_done",endpoint:s.endpoint,elapsedMs:s.elapsedMs}),h(`模型连接成功。
Endpoint${s.endpoint||d.endpoint}
耗时:${s.elapsedMs??"?"} ms
返回:${s.answer||""}`)):(c({stage:"llm_failed",endpoint:s.endpoint,elapsedMs:s.elapsedMs}),p(((t=s.error)==null?void 0:t.message)||`模型连接测试失败HTTP ${r}`))}catch(r){c({stage:"llm_failed"}),p(r instanceof Error?r.message:String(r))}finally{E(!1)}};return e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/65 backdrop-blur-sm p-4 sm:p-6",onMouseDown:n,children:e.jsxs("div",{className:"w-[calc(100vw-32px)] max-w-[1180px] h-[calc(100vh-64px)] max-h-[860px] rounded-lg border border-border-medium bg-surface shadow-2xl overflow-hidden flex flex-col",onMouseDown:t=>t.stopPropagation(),children:[e.jsxs("div",{className:"flex items-center justify-between px-5 py-4 border-b border-border-subtle bg-elevated/40",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-heading text-lg text-text-primary",children:"知识库混合 RAG 检索 / 问答"}),e.jsx("p",{className:"text-xs text-text-muted mt-1",children:"前端只发请求到本地后端;后端先检索证据,再代理调用模型并返回明确错误。"})]}),e.jsx("button",{type:"button",onClick:n,className:"text-text-muted hover:text-accent transition-colors text-xl leading-none",children:"×"})]}),e.jsxs("div",{className:"p-5 border-b border-border-subtle space-y-3",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("button",{type:"button",onClick:()=>{w("search"),N(!1)},className:`px-3 py-1.5 rounded-md border text-xs font-semibold ${x==="search"&&!y?"border-accent/50 bg-accent/20 text-accent":"border-border-subtle text-text-muted hover:text-text-primary"}`,children:"本地检索"}),e.jsx("button",{type:"button",onClick:()=>{w("llm"),N(!1)},className:`px-3 py-1.5 rounded-md border text-xs font-semibold ${x==="llm"&&!y?"border-accent/50 bg-accent/20 text-accent":"border-border-subtle text-text-muted hover:text-text-primary"}`,children:"大模型回答"}),e.jsx("button",{type:"button",onClick:()=>N(t=>!t),className:`px-3 py-1.5 rounded-md border text-xs font-semibold ${y?"border-accent/50 bg-accent/20 text-accent":"border-border-subtle text-text-muted hover:text-text-primary"}`,children:"模型设置"}),e.jsxs("div",{className:"text-[11px] text-text-muted",children:["图谱节点:",z,",文档节点:",F]})]}),y&&e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-[120px_160px_1fr_160px_100px] gap-2 border border-border-subtle rounded-lg p-3 bg-elevated/30",children:[e.jsxs("label",{className:"flex items-center gap-2 text-xs text-text-secondary",children:[e.jsx("input",{type:"checkbox",checked:d.enabled,onChange:t=>g({enabled:t.target.checked})}),"启用模型"]}),e.jsxs("select",{value:d.provider,onChange:t=>g({provider:t.target.value}),className:"bg-surface text-text-primary text-xs rounded px-2 py-1.5 border border-border-subtle focus:outline-none focus:border-accent/50",children:[e.jsx("option",{value:"auto",children:"自动识别"}),e.jsx("option",{value:"openai",children:"OpenAI兼容"}),e.jsx("option",{value:"routin-plan",children:"RoutIn Plan"})]}),e.jsx("input",{value:d.endpoint,onChange:t=>g({endpoint:t.target.value}),placeholder:"Base URLRoutIn Plan 填 https://api.routin.ai/plan/v1",className:"bg-surface text-text-primary text-xs rounded px-2 py-1.5 border border-border-subtle focus:outline-none focus:border-accent/50"}),e.jsx("input",{value:d.model,onChange:t=>g({model:t.target.value}),placeholder:"model",className:"bg-surface text-text-primary text-xs rounded px-2 py-1.5 border border-border-subtle focus:outline-none focus:border-accent/50"}),e.jsx("button",{type:"button",onClick:()=>void J(),disabled:M,className:"px-2 py-1.5 rounded border border-accent/30 text-xs text-accent disabled:opacity-60",children:M?"测试中":"测试连接"}),e.jsx("div",{className:"hidden md:block"}),e.jsx("div",{className:"hidden md:block text-[10px] text-text-muted pt-1",children:"plan- key 会走 /messages"}),e.jsx("input",{type:"password",value:d.apiKey,onChange:t=>g({apiKey:t.target.value}),placeholder:"API Key通过本地后端代理发送不从浏览器直连模型",className:"md:col-span-3 bg-surface text-text-primary text-xs rounded px-2 py-1.5 border border-border-subtle focus:outline-none focus:border-accent/50"})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("textarea",{value:i,onChange:t=>b(t.target.value),onKeyDown:t=>{(t.ctrlKey||t.metaKey)&&t.key==="Enter"&&P()},placeholder:"例如:黑名单是什么?回评是什么?对外 API 契约(草案);风险与反欺诈有哪些接口?",className:"flex-1 min-h-[76px] resize-none bg-elevated text-text-primary text-sm rounded-lg px-3 py-2 border border-border-subtle focus:outline-none focus:border-accent/50 placeholder-text-muted"}),e.jsx("button",{type:"button",onClick:()=>void P(),disabled:_,className:"px-4 py-2 rounded-lg bg-accent/20 text-accent hover:text-accent-bright border border-accent/30 text-sm font-semibold transition-colors disabled:opacity-60",children:_?"处理中":x==="llm"?"问答":"检索"})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3 text-[11px] text-text-muted",children:[e.jsx("span",{children:"快捷键Ctrl + Enter 提交。"}),e.jsxs("span",{children:["状态:",e.jsx("span",{className:"text-accent",children:G(l.stage)})]}),l.endpoint&&e.jsxs("span",{children:["Endpoint",l.endpoint]}),l.protocol&&e.jsxs("span",{children:["协议:",l.protocol]}),typeof l.elapsedMs=="number"&&e.jsxs("span",{children:["耗时:",l.elapsedMs," ms"]})]})]}),e.jsxs("div",{className:"flex-1 min-h-0 overflow-auto p-5 grid grid-cols-1 lg:grid-cols-[1fr_440px] gap-5",children:[e.jsxs("section",{className:"min-w-0 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("h3",{className:"text-[11px] font-semibold text-accent uppercase tracking-wider",children:"回答 / 请求状态"}),v&&j&&e.jsxs("span",{className:`text-[11px] ${j.allowed?"text-accent":"text-text-muted"}`,children:["证据判断:",j.reason]})]}),K&&e.jsxs("div",{className:"text-xs text-red-300 border border-red-400/30 bg-red-500/10 rounded p-2",children:["错误:",K]}),e.jsx("pre",{className:"whitespace-pre-wrap text-sm leading-relaxed text-text-secondary bg-elevated/50 border border-border-subtle rounded-lg p-4 font-sans min-h-[260px]",children:v||S?S||"等待后端返回。":"输入问题后点击“检索”或“问答”。"}),u&&e.jsxs("div",{className:"border border-border-subtle rounded-lg bg-elevated/40 p-3",children:[e.jsx("div",{className:"text-xs text-accent mb-1",children:"当前证据内容"}),e.jsxs("div",{className:"text-sm text-text-primary",children:[u.docTitle," / ",u.sectionTitle]}),e.jsx("div",{className:"text-[11px] text-text-muted mt-1",children:u.docPath}),e.jsx("pre",{className:"mt-2 max-h-[260px] overflow-auto whitespace-pre-wrap text-xs leading-relaxed text-text-secondary font-sans",children:u.evidenceContent||u.snippet})]})]}),e.jsxs("section",{className:"min-w-0",children:[e.jsx("h3",{className:"text-[11px] font-semibold text-accent uppercase tracking-wider mb-2",children:"本地命中证据与排序依据"}),e.jsxs("div",{className:"space-y-2",children:[k.length===0&&v&&e.jsx("div",{className:"text-sm text-text-muted border border-border-subtle rounded-lg p-3",children:"暂无命中。"}),k.slice(0,12).map(t=>e.jsxs("div",{className:"border border-border-subtle bg-elevated/40 hover:border-accent/40 rounded-lg p-3 transition-colors",children:[e.jsxs("button",{type:"button",onClick:()=>f(t.nodeId),className:"w-full text-left",children:[e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-sm text-text-primary truncate",children:t.docTitle}),e.jsx("div",{className:"text-[11px] text-accent mt-1 truncate",children:t.sectionTitle})]}),e.jsx("div",{className:"text-[11px] text-accent shrink-0",children:t.score.toFixed(1)})]}),e.jsx("div",{className:"text-[11px] text-text-muted mt-1 truncate",children:t.docPath})]}),e.jsx("button",{type:"button",onClick:()=>$(t),className:"mt-2 text-left text-xs text-text-secondary line-clamp-4 hover:text-text-primary",children:t.snippet}),e.jsxs("div",{className:"mt-2 grid grid-cols-4 gap-1 text-[10px] text-text-muted",children:[e.jsxs("span",{children:["exact ",t.scores.exact.toFixed(0)]}),e.jsxs("span",{children:["fuzzy ",t.scores.fuzzy.toFixed(0)]}),e.jsxs("span",{children:["semantic ",t.scores.semantic.toFixed(0)]}),e.jsxs("span",{children:["boost ",(t.scores.titleBoost+t.scores.sectionBoost+t.scores.directoryBoost+t.scores.chunkTypeBoost).toFixed(0)]})]}),e.jsx("div",{className:"mt-2 flex flex-wrap gap-1",children:t.reasons.slice(0,5).map((r,s)=>e.jsxs("span",{className:"text-[10px] text-text-muted border border-border-subtle rounded px-1.5 py-0.5",children:[r.message," +",r.score.toFixed(0)]},`${t.chunkId}-${s}`))})]},t.chunkId))]})]})]})]})})}export{ee as default};