Files
Fulfilled-Knowledge/wishfulfilled-dashboard/assets/RagAssistant-Dy1Qzujc.js
2026-05-27 15:40:32 +08:00

24 lines
18 KiB
JavaScript
Raw Permalink 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 as b,j as i}from"./react-vendor-BVoutfaX.js";import{u as P}from"./index-DGED3sP8.js";import"./xyflow-CYMCcsWN.js";import"./graph-layout-7tFr_anw.js";import"./elk-CXeXGyKz.js";import"./graphology-BgTy_cc3.js";const B="ua-rag-llm-settings-v1",F={回评:["评价提交","评价展示","客服邀评","评价结果追踪","review submission","review display","review follow-up"],测评:["评价计划","review plan","评价提交","额度统计","测评单"],免评:["KOC","KOL","内容发布","引流","带货","exemption"],真实人:["person","person_profiles","跨账号归并","身份归并","真实人归并"],额度:["4/4/12","person_quota_ledgers","额度台账","预占","额度与频控"],对外API:["对外 API 契约","接口契约","API 草案","接口说明","对外接口"],工单:["客服工单","support_tickets","客服跟进","support_followups"],风险:["风险与反欺诈","risk_signals","risk_cases","黑名单","反欺诈"]};function E(t){return Array.isArray(t)?t.join(" "):typeof t=="string"?t:""}function q(t){return t.replace(/<script[\s\S]*?<\/script>/gi," ").replace(/<style[\s\S]*?<\/style>/gi," ").replace(/<[^>]+>/g," ").replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">")}function Q(t){const e=t.split(`
`);let n=0;const a=e.map(s=>{const o=s.match(/^\s*\d+\|(.+)$/);return o?(n+=1,o[1]):s});return n>=Math.max(3,Math.floor(e.length/4))?a.join(`
`):t}function f(t){return t.toLowerCase().replace(/[\s`*_>#|\-\[\]()()【】《》“”"',。、::;,.\/\\!?]+/g,"")}function j(t){return q(Q(t)).toLowerCase().replace(/[\t\r]+/g," ").replace(/[]/g," ").replace(/[【】《》“”]/g," ").replace(/[_*`>#|\[\]]/g," ").replace(/\s+/g," ").trim()}function T(t){return Array.from(new Set(t.map(e=>e.trim()).filter(Boolean)))}function M(t){const e=j(t),n=e.match(/[a-z0-9_./+-]{2,}/g)??[],a=e.match(/[\u4e00-\u9fa5]{2,}/g)??[],s=e.match(/[\u4e00-\u9fa5]/g)??[],o=[];for(let c=0;c<s.length-1;c+=1)o.push(`${s[c]}${s[c+1]}`);for(let c=0;c<s.length-2;c+=1)o.push(`${s[c]}${s[c+1]}${s[c+2]}`);return T([...n,...a,...o,...s.filter(c=>!/[是什么吗呢的了和与及或在中为]/.test(c))])}function H(t){const e=j(t);return/api|接口|契约|endpoint|对外/.test(e)?"api":/数据|字段|表|对象|模型|schema|建表/.test(e)?"data_model":/流程|怎么走|如何|步骤|流转|处理/.test(e)?"process":/规则|限制|口径|额度|频控|条件/.test(e)?"rule":/谁|负责|职责|owner|角色/.test(e)?"responsibility":/测试|验收|用例|缺陷|上线/.test(e)?"test":/里程碑|阶段|计划|节点/.test(e)?"milestone":/是什么|定义|含义|意思|解释/.test(e)?"definition":"general"}function R(t,e){const n=f(e),a=[];for(const[s,o]of Object.entries(F)){const c=f(s);(n.includes(c)||t.some(r=>f(r).includes(c)||c.includes(f(r))))&&a.push(s,...o)}return T(a)}function J(t){const e=j(t),n=f(t),a=M(t),s=R(a,t),o=T([t.trim(),e,n,...a.filter(c=>c.length>=2)]);return{raw:t,normalized:e,compact:n,tokens:a,coreTerms:o,expandedTerms:s,questionType:H(t)}}function Y(t){var e;return q(Q(E((e=t.knowledgeMeta)==null?void 0:e.content)))}function G(t){var e;return E((e=t.knowledgeMeta)==null?void 0:e.category)||t.tags.find(n=>n.includes("需求")||n.includes("技术")||n.includes("测试")||n.includes("里程碑"))||""}function U(t,e){const n=`${t}
${e}`.toLowerCase();return/api|接口|契约|endpoint|对外/.test(n)?"api_contract":/数据模型|字段|表结构|对象|schema|建表/.test(n)?"data_model":/业务规则|规则|口径|额度|频控|限制/.test(n)?"business_rule":/流程|流转|步骤|时序|处理/.test(n)?"process":/faq|常见问题|是什么|问答/.test(n)?"faq":"general"}function V(t){var o,c;const e=t.trim();if(!e)return[];const n=[];let a="全文",s=[];for(const r of e.split(`
`)){const u=(c=(o=r.match(/^\s{0,3}#{1,6}\s+(.+)$/))==null?void 0:o[1])==null?void 0:c.trim();u?(s.length>0&&n.push({heading:a,text:s.join(`
`)}),a=u,s=[r]):s.push(r)}return s.length>0&&n.push({heading:a,text:s.join(`
`)}),n.length>0?n:[{heading:"全文",text:e}]}function W(t){return t.flatMap(e=>{const n=Y(e),a=[e.name,e.summary,e.filePath,e.tags.join(" ")].join(`
`);return V(n||a).map((o,c)=>{const r=o.text.trim()||a,u=j(r);return{chunkId:`${e.id}#${c}`,node:e,docTitle:e.name,docPath:e.filePath??e.id,sectionTitle:o.heading,content:r,normalizedContent:u,compactContent:f(r),chunkType:U(o.heading,r),layer:G(e)}})})}function K(t,e){return e?t.split(e).length-1:0}function C(t,e,n,a=1){const s=j(t),o=f(t),c=[];let r=0;const u=T([e.normalized,e.raw.toLowerCase()].filter(p=>p.length>=2));for(const p of u)if(s.includes(p)){const m=70*a;r+=m,c.push({type:"exact",field:n,message:`${n} 原文命中:${p}`,score:m})}if(e.compact&&o.includes(e.compact)){const p=80*a;r+=p,c.push({type:"compact",field:n,message:`${n} 去标点命中`,score:p})}let d=0;for(const p of e.coreTerms){const m=j(p),x=f(p);if(!m&&!x)continue;const h=Math.max(K(s,m),K(o,x));h>0&&(d+=1,r+=Math.min(h,4)*Math.min(Math.max(x.length,m.length),10)*a)}return d>0&&c.push({type:"token",field:n,message:`${n} 关键词覆盖 ${d}`,score:d*a}),{score:r,reasons:c}}function X(t,e){const n=[],a=T([...e.tokens,...e.expandedTerms.flatMap(M)]).filter(u=>u.length>=2);if(a.length===0)return{score:0,reasons:n};const s=new Set(M(`${t.docTitle} ${t.sectionTitle} ${t.normalizedContent}`));let o=0;for(const u of a)(s.has(u)||t.compactContent.includes(f(u))||f(`${t.docTitle}${t.sectionTitle}`).includes(f(u)))&&(o+=1);const c=o/Math.max(a.length,1),r=c*90;return r>0&&n.push({type:"semantic",message:`语义/同义词覆盖 ${(c*100).toFixed(0)}%`,score:r}),{score:r,reasons:n}}function Z(t,e){const n=t.docPath,a=n.includes("05_需求文档")?15:n.includes("01_业务流程")?12:n.includes("07_技术文档")?10:n.includes("08_测试相关")?8:n.includes("06_里程碑")?6:n.includes("02_项目管理流程")?5:n.includes("04_Agent检索")?4:n.includes("03_规范与模板")?1:0;return e.questionType==="api"&&n.includes("07_技术文档")?a+8:(e.questionType==="definition"||e.questionType==="rule")&&n.includes("05_需求文档")?a+5:e.questionType==="test"&&n.includes("08_测试相关")?a+12:a}function ee(t,e){return e.questionType==="api"&&t.chunkType==="api_contract"||e.questionType==="data_model"&&t.chunkType==="data_model"?18:e.questionType==="process"&&t.chunkType==="process"||e.questionType==="rule"&&t.chunkType==="business_rule"?14:e.questionType==="definition"&&(t.chunkType==="faq"||t.sectionTitle.includes("概述")||t.sectionTitle.includes("目标"))?10:0}function te(t,e){const n=t.replace(/\s+/g," ").trim();if(!n)return"";const a=n.toLowerCase(),s=f(n),c=T([e.normalized,e.raw,e.compact,...e.coreTerms,...e.expandedTerms]).map(d=>{const p=a.indexOf(j(d));if(p>=0)return p;const m=s.indexOf(f(d));return m>=0?Math.min(m,n.length-1):-1}).filter(d=>d>=0).sort((d,p)=>d-p)[0],r=Math.max(0,(c??0)-110),u=n.slice(r,r+320);return`${r>0?"…":""}${u}${r+320<n.length?"…":""}`}function O(t,e){const n=J(e);if(!n.normalized&&!n.compact)return[];const a=n.questionType==="api"?{exact:.45,fuzzy:.25,semantic:.1}:n.questionType==="definition"||n.questionType==="process"?{exact:.25,fuzzy:.2,semantic:.3}:{exact:.3,fuzzy:.2,semantic:.25};return t.map(s=>{const o=C(`${s.docTitle}
${s.docPath}`,n,"docTitle",4),c=C(s.sectionTitle,n,"sectionTitle",6),r=C(s.normalizedContent,n,"content",1),u=C(s.node.tags.join(" "),n,"tags",3),d=X(s,n),p=o.score+c.score+u.score+r.score,m=(s.compactContent.includes(n.compact)?80:0)+r.score*.2,x=o.score>0?12:0,h=c.score>0?18:0,g=Z(s,n),w=ee(s,n),k=p*a.exact+m*a.fuzzy+d.score*a.semantic+x+h+g+w,v=[...o.reasons,...c.reasons,...u.reasons,...r.reasons.slice(0,3),...d.reasons];return g&&v.push({type:"directory",message:`目录权重:${s.docPath.split("/")[0]??""}`,score:g}),w&&v.push({type:"chunkType",message:`章节类型匹配:${s.chunkType}`,score:w}),{chunk:s,score:k,scores:{exact:p,fuzzy:m,semantic:d.score,titleBoost:x,sectionBoost:h,directoryBoost:g,chunkTypeBoost:w},snippet:te(s.content,n),reasons:v}}).filter(s=>s.score>10&&s.snippet).sort((s,o)=>o.score-s.score).reduce((s,o)=>{const c=`${o.chunk.node.id}:${o.chunk.sectionTitle}`;return s.some(r=>`${r.chunk.node.id}:${r.chunk.sectionTitle}`===c)||s.push(o),s},[]).slice(0,16)}function I(t,e){var n;return t.trim()?e.length===0?{allowed:!1,reason:"没有检索到相关证据。"}:e[0].score>=75?{allowed:!0,reason:"Top1 证据分数达到阈值。"}:e[0].score>=60&&(((n=e[1])==null?void 0:n.score)??0)>=50?{allowed:!0,reason:"多个证据片段达到中等相关。"}:{allowed:!1,reason:"证据分数不足。"}:{allowed:!1,reason:"请输入问题。"}}function z(t,e){if(!t.trim())return"请输入要检索或提问的内容。";const n=I(t,e);if(!n.allowed)return"暂无该需求描述。";const a=e.slice(0,5);return[`结论:已基于本地知识库检索到可用证据。${n.reason}`,"","相关依据:",...a.map((s,o)=>`${o+1}. ${s.chunk.docTitle}${s.chunk.sectionTitle?` / ${s.chunk.sectionTitle}`:""}
${s.snippet}
来源:${s.chunk.docPath}`),"","说明:当前本地模式不调用大模型,只返回可追溯证据摘要。切换到“大模型回答”可基于这些证据生成解释性回答。"].join(`
`)}function ne(){if(typeof window>"u")return{enabled:!1,endpoint:"http://localhost:11434/v1/chat/completions",model:"qwen2.5:7b",apiKey:""};try{const t=window.localStorage.getItem(B);if(t)return{enabled:!1,endpoint:"http://localhost:11434/v1/chat/completions",model:"qwen2.5:7b",apiKey:"",...JSON.parse(t)}}catch{}return{enabled:!1,endpoint:"http://localhost:11434/v1/chat/completions",model:"qwen2.5:7b",apiKey:""}}function se(t){typeof window>"u"||window.localStorage.setItem(B,JSON.stringify(t))}async function oe(t,e,n){var d,p,m,x;if(!I(e,n).allowed)return"暂无该需求描述。";if(!t.enabled||!t.endpoint||!t.model)return z(e,n);const s=n.slice(0,8).map((h,g)=>`[${g+1}]
来源:${h.chunk.docPath}
章节:${h.chunk.sectionTitle}
内容:${h.snippet}`).join(`
`),o=[{role:"system",content:"你是如愿知识库问答助手。你只能基于提供的知识库片段回答,不得使用外部知识,不得编造文档中没有的内容。如果证据不足,请只回答:暂无该需求描述。回答末尾必须列出来源文件。"},{role:"user",content:`用户问题:
${e}
检索证据:
${s}
请用中文结构化回答。`}],c=await fetch(t.endpoint,{method:"POST",headers:{"Content-Type":"application/json",...t.apiKey?{Authorization:`Bearer ${t.apiKey}`}:{}},body:JSON.stringify({model:t.model,messages:o,temperature:.1,stream:!1})});if(!c.ok)throw new Error(`LLM request failed: ${c.status} ${c.statusText}`);const r=await c.json(),u=((m=(p=(d=r==null?void 0:r.choices)==null?void 0:d[0])==null?void 0:p.message)==null?void 0:m.content)??((x=r==null?void 0:r.message)==null?void 0:x.content)??(r==null?void 0:r.response);return typeof u=="string"&&u.trim()?u.trim():"暂无该需求描述。"}function ue({onClose:t}){const e=P(l=>l.graph),n=P(l=>l.navigateToNodeInLayer),[a,s]=b.useState(""),[o,c]=b.useState(""),[r,u]=b.useState("search"),[d,p]=b.useState(ne),[m,x]=b.useState(""),[h,g]=b.useState(!1),[w,k]=b.useState(null),[v,D]=b.useState(!1),S=b.useMemo(()=>W((e==null?void 0:e.nodes)??[]),[e]),$=b.useMemo(()=>O(S,o),[S,o]),A=b.useMemo(()=>I(o,$),[o,$]),_=l=>{const y={...d,...l};p(y),se(y)},L=async()=>{const l=a.trim();if(c(l),k(null),!l){x("请输入要检索或提问的内容。");return}const y=O(S,l);if(r==="search"){x(z(l,y));return}g(!0);try{x(await oe(d,l,y))}catch(N){k(N instanceof Error?N.message:String(N)),x(z(l,y))}finally{g(!1)}};return i.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:t,children:i.jsxs("div",{className:"w-[calc(100vw-32px)] max-w-[1120px] h-[calc(100vh-64px)] max-h-[820px] rounded-lg border border-border-medium bg-surface shadow-2xl overflow-hidden flex flex-col",onMouseDown:l=>l.stopPropagation(),children:[i.jsxs("div",{className:"flex items-center justify-between px-5 py-4 border-b border-border-subtle bg-elevated/40",children:[i.jsxs("div",{children:[i.jsx("h2",{className:"font-heading text-lg text-text-primary",children:"知识库混合 RAG 检索 / 问答"}),i.jsx("p",{className:"text-xs text-text-muted mt-1",children:"先精确匹配标题、章节和原文,再做模糊/语义补充,并展示排序依据。"})]}),i.jsx("button",{type:"button",onClick:t,className:"text-text-muted hover:text-accent transition-colors text-xl leading-none",children:"×"})]}),i.jsxs("div",{className:"p-5 border-b border-border-subtle space-y-3",children:[i.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[i.jsx("button",{type:"button",onClick:()=>u("search"),className:`px-3 py-1.5 rounded-md border text-xs font-semibold ${r==="search"?"border-accent/50 bg-accent/20 text-accent":"border-border-subtle text-text-muted hover:text-text-primary"}`,children:"本地检索"}),i.jsx("button",{type:"button",onClick:()=>u("llm"),className:`px-3 py-1.5 rounded-md border text-xs font-semibold ${r==="llm"?"border-accent/50 bg-accent/20 text-accent":"border-border-subtle text-text-muted hover:text-text-primary"}`,children:"大模型回答"}),i.jsx("button",{type:"button",onClick:()=>D(l=>!l),className:"px-3 py-1.5 rounded-md border border-border-subtle text-xs text-text-muted hover:text-text-primary",children:"模型设置"}),i.jsxs("div",{className:"text-[11px] text-text-muted",children:["文档节点:",(e==null?void 0:e.nodes.length)??0,",切片:",S.length]})]}),v&&i.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-[120px_1fr_160px] gap-2 border border-border-subtle rounded-lg p-3 bg-elevated/30",children:[i.jsxs("label",{className:"flex items-center gap-2 text-xs text-text-secondary",children:[i.jsx("input",{type:"checkbox",checked:d.enabled,onChange:l=>_({enabled:l.target.checked})}),"启用模型"]}),i.jsx("input",{value:d.endpoint,onChange:l=>_({endpoint:l.target.value}),placeholder:"OpenAI/Ollama compatible endpoint",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"}),i.jsx("input",{value:d.model,onChange:l=>_({model:l.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"}),i.jsx("div",{className:"hidden md:block"}),i.jsx("input",{value:d.apiKey,onChange:l=>_({apiKey:l.target.value}),placeholder:"API Key可空仅保存在浏览器本地",className:"md:col-span-2 bg-surface text-text-primary text-xs rounded px-2 py-1.5 border border-border-subtle focus:outline-none focus:border-accent/50"})]}),i.jsxs("div",{className:"flex gap-2",children:[i.jsx("textarea",{value:a,onChange:l=>s(l.target.value),onKeyDown:l=>{(l.ctrlKey||l.metaKey)&&l.key==="Enter"&&L()},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"}),i.jsx("button",{type:"button",onClick:()=>void L(),disabled:h,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:h?"处理中":r==="llm"?"问答":"检索"})]}),i.jsx("div",{className:"text-[11px] text-text-muted",children:"快捷键Ctrl + Enter 提交。大模型模式会先执行本地混合检索;证据不足返回“暂无该需求描述”。"})]}),i.jsxs("div",{className:"flex-1 min-h-0 overflow-auto p-5 grid grid-cols-1 lg:grid-cols-[1fr_420px] gap-5",children:[i.jsxs("section",{className:"min-w-0",children:[i.jsxs("div",{className:"flex items-center justify-between mb-2",children:[i.jsx("h3",{className:"text-[11px] font-semibold text-accent uppercase tracking-wider",children:"回答"}),o&&i.jsxs("span",{className:`text-[11px] ${A.allowed?"text-accent":"text-text-muted"}`,children:["证据判断:",A.reason]})]}),i.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:o?m||z(o,$):"输入问题后点击“检索”或“问答”。"}),w&&i.jsxs("div",{className:"mt-2 text-xs text-red-300 border border-red-400/30 bg-red-500/10 rounded p-2",children:["模型调用失败,已回退到本地检索:",w]})]}),i.jsxs("section",{className:"min-w-0",children:[i.jsx("h3",{className:"text-[11px] font-semibold text-accent uppercase tracking-wider mb-2",children:"命中文档与排序依据"}),i.jsxs("div",{className:"space-y-2",children:[$.length===0&&o&&i.jsx("div",{className:"text-sm text-text-muted border border-border-subtle rounded-lg p-3",children:"暂无命中。"}),$.slice(0,12).map(l=>i.jsxs("button",{type:"button",onClick:()=>n(l.chunk.node.id),className:"w-full text-left border border-border-subtle bg-elevated/40 hover:border-accent/40 rounded-lg p-3 transition-colors",children:[i.jsxs("div",{className:"flex items-start justify-between gap-2",children:[i.jsxs("div",{className:"min-w-0",children:[i.jsx("div",{className:"text-sm text-text-primary truncate",children:l.chunk.docTitle}),i.jsx("div",{className:"text-[11px] text-accent mt-1 truncate",children:l.chunk.sectionTitle})]}),i.jsx("div",{className:"text-[11px] text-accent shrink-0",children:l.score.toFixed(1)})]}),i.jsx("div",{className:"text-[11px] text-text-muted mt-1 truncate",children:l.chunk.docPath}),i.jsx("div",{className:"text-xs text-text-secondary mt-2 line-clamp-3",children:l.snippet}),i.jsx("div",{className:"mt-2 flex flex-wrap gap-1",children:l.reasons.slice(0,4).map((y,N)=>i.jsxs("span",{className:"text-[10px] text-text-muted border border-border-subtle rounded px-1.5 py-0.5",children:[y.message," +",y.score.toFixed(0)]},`${l.chunk.chunkId}-${N}`))})]},l.chunk.chunkId))]})]})]})]})})}export{ue as default};