Major Changes: - Add StreamingService with OpenAI Compatible format - Upgrade Chat component V2 with Ant Design X integration - Implement AIA module with 12 intelligent agents - Update API routes to unified /api/v1 prefix - Update system documentation Backend (~1300 lines): - common/streaming: OpenAI Compatible adapter - modules/aia: 12 agents, conversation service, streaming integration - Update route versions (RVW, PKB to v1) Frontend (~3500 lines): - modules/aia: AgentHub + ChatWorkspace (100% prototype restoration) - shared/Chat: AIStreamChat, ThinkingBlock, useAIStream Hook - Update API endpoints to v1 Documentation: - AIA module status guide - Universal capabilities catalog - System overview updates - All module documentation sync Tested: Stream response verified, authentication working Status: AIA V2.0 core completed (85%)
178 lines
7.7 KiB
Markdown
178 lines
7.7 KiB
Markdown
# **<2A><><EFBFBD>航挽霈⊥<E99C88>獢<EFBFBD><E78DA2>撌亙<E6928C> B \- <20><><EFBFBD>蝏𤘪<E89D8F><F0A498AA>𡝗㦤<F0A19D97>其犖 (The AI Structurer)**
|
||
|
||
| <20><>﹝蝐餃<E89D90> | Technical Design Document (TDD) |
|
||
| :---- | :---- |
|
||
| **撖孵<E69296> PRD** | **PRD\_撌亙<E6928C>B\_<><5F><EFBFBD>蝏𤘪<E89D8F><F0A498AA>𡝗㦤<F0A19D97>其犖\_V2.md** |
|
||
| **<EFBFBD><EFBFBD>𧋦** | **V2.0** (<28>嗆<EFBFBD><E59786><EFBFBD>漣嚗𡁜<E59A97>璅∪<E79285>鈭文<E988AD>撉諹<E69289>) |
|
||
| **<EFBFBD>嗆<EFBFBD>?* | Draft |
|
||
| **<EFBFBD>詨<EFBFBD><EFBFBD>格<EFBFBD>** | <20><>遣銝<E981A3>銝芷<E98A9D><E88AB7>臭縑摨衣<E691A8><E8A1A3>餌<EFBFBD><E9A48C><EFBFBD>𧋦蝏𤘪<E89D8F><F0A498AA>硋<EFBFBD><E7A18B>𠬍<EFBFBD><F0A0AC8D>朞<EFBFBD>**<2A>峕芋<E5B395>页<EFBFBD>DeepSeek & Qwen嚗匧僎<E58CA7>烐<EFBFBD><E78390>?*銝?*<2A>芸𢆡鈭文<E988AD>撉諹<E69289>**嚗諹圾<E8ABB9>?AI 撟餉<E6929F><E9A489>桅<EFBFBD><E6A185>?|
|
||
|
||
## **1\. <20>颱<EFBFBD><E9A2B1>嗆<EFBFBD>霈曇恣 (Architecture Overview)**
|
||
|
||
蝟餌<EFBFBD><EFBFBD>嗆<EFBFBD>隞𢛶<EFBFBD>𨅯<EFBFBD>蝥踵<EFBFBD>扳<EFBFBD>瘞渡瑪<EFBFBD>嘥<EFBFBD>蝥找蛹 **<EFBFBD>陖<EFBFBD>见僎<EFBFBD>烐<EFBFBD>瘞渡瑪<EFBFBD>?*<2A><>㺭<EFBFBD>株<EFBFBD><E6A0AA>亙<EFBFBD>嚗<EFBFBD><E59A97><EFBFBD>𤑳<EFBFBD>銝支葵銝滚<E98A9D><E6BB9A>?LLM 璅∪<E79285>撟嗉<E6929F>憭<EFBFBD><E686AD>嚗𣬚<E59A97><F0A3AC9A>𨀣<EFBFBD><F0A880A3>𡁜<EFBFBD><F0A1819C>𨅯<EFBFBD>蝒<EFBFBD><E89D92>瘚见<E7989A><E8A781>𢛶<EFBFBD>肽<EFBFBD>銵峕<E98AB5>撖對<E69296><E5B08D><EFBFBD><EFBFBD>舘<EFBFBD><E88898>箏<EFBFBD>鈭箏極撉諹<E69289>蝵烐聢<E78390>?
|
||
### **1.1 蝟餌<E89D9F><E9A48C>嗆<EFBFBD><E59786>?*
|
||
|
||
graph TD
|
||
Client\[React <20>滨垢 (Grid & Drawer UI)\]
|
||
|
||
subgraph API\_Server \[Fastify API <20>滚𦛚\]
|
||
JobAPI\[隞餃𦛚銝擧芋<E693A7><E88A8B>𦻖<EFBFBD>α]
|
||
VerifyAPI\[<5B>冽艶蝵烐聢<E78390>亙藁\]
|
||
end
|
||
|
||
subgraph Async\_Cluster \[<5B>𤾸蝱 Worker <20><>黎\]
|
||
BullMQ\[BullMQ 隞餃𦛚<E9A483>笔<EFBFBD>\]
|
||
Orchestrator\[隞餃𦛚蝻𡝗<E89DBB><F0A19D97>沔]
|
||
PII\_Engine\[<5B>鞟<EFBFBD><E99E9F>望<EFBFBD>撘閙<E69298>\]
|
||
|
||
subgraph Dual\_LLM\_Engine \[<5B>𣬚𤩅<F0A3AC9A>𣂼<EFBFBD>撘閙<E69298>\]
|
||
ClientA\[DeepSeek 摰X<E691B0>蝡珮]
|
||
ClientB\[Qwen 摰X<E691B0>蝡珮]
|
||
end
|
||
|
||
CrossValidator\[鈭文<E988AD>撉諹<E69289>/<2F>脩<EFBFBD>璉<EFBFBD>瘚见膥\]
|
||
end
|
||
|
||
subgraph Storage \[<5B>唳旿摮睃<E691AE>\]
|
||
PG\[(PostgreSQL \- 銝𡁜𦛚<F0A1819C>唳旿)\]
|
||
VectorDB\[(pgvector \- <20>舫<EFBFBD>㚁<EFBFBD><E39A81>其<EFBFBD>霂凋<E99C82>瘥𥪜笆)\]
|
||
Redis\[(Redis \- <20>笔<EFBFBD>)\]
|
||
end
|
||
|
||
Client \--1.銝𠹺<E98A9D>&雿𤘪<E99BBF>--\> JobAPI
|
||
JobAPI \--2.<2E>𥕦遣撟嗅<E6929F>隞餃𦛚--\> BullMQ
|
||
BullMQ \--3.瘨<>晶--\> Orchestrator
|
||
Orchestrator \--4.<2E>望<EFBFBD>--\> PII\_Engine
|
||
PII\_Engine \--5.撟嗉<E6929F>靚<EFBFBD>鍂--\> ClientA & ClientB
|
||
ClientA & ClientB \--6.餈𥪜<E9A488>JSON--\> CrossValidator
|
||
CrossValidator \--7.霈∠<E99C88>銝<EFBFBD><E98A9D>湔<EFBFBD>?-\> PG
|
||
Client \--8.<2E>匧<EFBFBD>蝵烐聢<E78390>唳旿--\> VerifyAPI
|
||
VerifyAPI \--9.鈭箏極鋆<E6A5B5><E98B86>--\> PG
|
||
|
||
## **2\. <20><><EFBFBD>舫<EFBFBD>匧<EFBFBD> (Tech Stack)**
|
||
|
||
| 撅<>漣 | <20><><EFBFBD>舐<EFBFBD>隞?| <20>匧<EFBFBD><E58CA7><EFBFBD>眏 |
|
||
| :---- | :---- | :---- |
|
||
| **<EFBFBD>𡒊垢獢<EFBFBD>沲** | **Fastify 5.x** | 擃䀹<E69383>扯<EFBFBD>撘<EFBFBD>郊 I/O嚗屸<E59A97><E5B1B8><EFBFBD>憭<EFBFBD><E686AD>擃睃僎<E79D83>烐芋<E78390>贝<EFBFBD><E8B49D>具<EFBFBD>?|
|
||
| **璅∪<E79285><E288AA>亙<EFBFBD>** | **LangChain.js** | 蝏煺<E89D8F>撠<EFBFBD><E692A0> DeepSeek <20>?Qwen <20><><EFBFBD><EFBFBD>冽𦻖<E586BD><F0A6BB96><EFBFBD>靘蹂<E99D98><E8B982><EFBFBD>揢璅∪<E79285><E288AA>?|
|
||
| **隞餃𦛚<E9A483>笔<EFBFBD>** | **BullMQ** | <20>詨<EFBFBD>蝏<EFBFBD>辣<EFBFBD><E8BEA3>2 <20><>閬<EFBFBD>⏚<EFBFBD>?Flow <20>蠘<EFBFBD><E8A098>𡝗<EFBFBD><F0A19D97>函<EFBFBD><E587BD>埝䔉摰䂿緵<E482BF>𦦵<EFBFBD>敺<EFBFBD>舅銝芣芋<E88AA3>钅<EFBFBD>餈𥪜<E9A488><F0A5AA9C>萘<EFBFBD><E89098>餉<EFBFBD><E9A489>?|
|
||
| **<EFBFBD>脩<EFBFBD>璉<EFBFBD>瘚?* | **Lodash (<28>箇<EFBFBD>) \+ Dice Coefficient (餈偦𧫴)** | <20>其<EFBFBD>瘥𥪜笆銝支葵 JSON 撖寡情<E5AFA1><E68385><EFBFBD>畾萄榆撘<E6A686><E69298><EFBFBD><EFBFBD><EFBFBD>祉㮾隡澆漲<E6BE86>臭蝙<E887AD>函<EFBFBD><E587BD>閧<EFBFBD> Dice 蝟餅㺭<E9A485>?Levenshtein 頝萘氖嚗峕<E59A97>銝漤<E98A9D>閬<EFBFBD><E996AC><EFBFBD>见<EFBFBD><E8A781>誩<EFBFBD><E8AAA9>?|
|
||
| **<EFBFBD>唳旿摨?* | **PostgreSQL 15** | 摮睃<E691AE> JSONB <20>澆<EFBFBD><E6BE86><EFBFBD><EFBFBD>璅∪<E79285>蝏𤘪<E89D8F><F0A498AA>?|
|
||
| **<EFBFBD>滨垢鈭支<EFBFBD>** | **React \+ TanStack Table** | V2 <20>嫣蛹<E5ABA3>冽艶蝵烐聢嚗峕㺭<E5B395>桅<EFBFBD>憭扳𧒄<E689B3><F0A79284>閬?TanStack Table (Headless) <20>滚<EFBFBD><E6BB9A>𡁏<EFBFBD>皛𡁜𢆡<F0A1819C>?|
|
||
|
||
## **3\. <20>詨<EFBFBD>瘚<EFBFBD><E7989A>霈曇恣 (Core Logic)**
|
||
|
||
### **3.1 <20>箄<EFBFBD>雿𤘪<E99BBF> (Health Check Logic)**
|
||
|
||
* **閫血<E996AB><E8A180>嗆㦤嚗?* <20>冽<EFBFBD><E586BD>典<EFBFBD>蝡舫<E89DA1>㗇𥋘<E39787>𨀣<EFBFBD><F0A880A3>砍<EFBFBD><E7A08D>萘<EFBFBD><E89098>祇𡢿<E7A587>?
|
||
* **<2A>扯<EFBFBD><E689AF>餉<EFBFBD>嚗?*
|
||
1. <20>𡒊垢霂餃<E99C82>霂亙<E99C82><E4BA99><EFBFBD><EFBFBD> 100 銵䕘<E98AB5>銝滩粉<E6BBA9>券<EFBFBD>嚗剹<E59A97>?
|
||
2. 霈∠<E99C88>蝏蠘恣<E8A098><E681A3><EFBFBD>嚗?
|
||
* emptyRate: 蝛箏<E89D9B>?/ <20>餉<EFBFBD><E9A489>啜<EFBFBD>?
|
||
* avgLength: <20>䂿征銵𣬚<E98AB5>撟喳<E6929F>摮㛖泵<E39B96>啜<EFBFBD>?
|
||
3. **<EFBFBD>行⏛蝑𣇉裦嚗?* <20>?emptyRate \> 0.8 <20>?avgLength \< 10嚗諹<E59A97><E8ABB9>?status: 'BAD'<27>?
|
||
4. **Token 憸<>摯嚗?* totalRows \* avgLength \* 1.5 (蝎㛖裦隡啁<E99AA1>)<29>?
|
||
### **3.2 <20>𣬚𤩅<F0A3AC9A>𣂼<EFBFBD>銝𦒘漱<F0A69298>厰<EFBFBD>霂?(Double-Blind & Validation)**
|
||
|
||
餈蹱糓 V2 <20><><EFBFBD><EFBFBD>譌<EFBFBD>?
|
||
#### **A. <20>鞟內霂滚極蝔?(Prompt Engineering)**
|
||
|
||
銝箔<EFBFBD><EFBFBD>嫣噶瘥𥪜笆嚗<EFBFBD><EFBFBD>憿餃撩<EFBFBD>嗡舅銝芣芋<EFBFBD>贝<EFBFBD><EFBFBD>?*摰<><E691B0>銝<EFBFBD><E98A9D>渡<EFBFBD> JSON 蝏𤘪<E89D8F>**<2A>?
|
||
* **System Prompt:** "You are a medical structural extraction assistant..."
|
||
* **Constraint:** "Output strictly in JSON format. Keys must be: \['tumor\_size', 'lymph\_node', ...\]."
|
||
* **Temperature:** 霈曆蛹 0嚗諹蕭瘙<E895AD><E79899>憭抒&摰𡁏<E691B0>扼<EFBFBD>?
|
||
#### **B. 鈭文<E988AD>撉諹<E69289>蝞埈<E89D9E> (The Judge)**
|
||
|
||
敶?Model A (DeepSeek) <20>?Model B (Qwen) 餈𥪜<E9A488>蝏𤘪<E89D8F><F0A498AA>𠬍<EFBFBD><F0A0AC8D>扯<EFBFBD>瘥𥪜笆嚗?
|
||
function validate(jsonA, jsonB) {
|
||
const conflicts \= \[\];
|
||
const keys \= Object.keys(jsonA);
|
||
|
||
for (const key of keys) {
|
||
const valA \= normalize(jsonA\[key\]); // 敶雴<E695B6><E99BB4>吔<EFBFBD><E59094>駁膄蝛箸聢<E7AEB8><E881A2>蓮撠誩<E692A0><E8AAA9><EFBFBD><EFBFBD>閫鍦<E996AB>
|
||
const valB \= normalize(jsonB\[key\]);
|
||
|
||
// 1\. 蝎曄&<E69B84>寥<EFBFBD>
|
||
if (valA \=== valB) continue;
|
||
|
||
// 2\. <20>啣<EFBFBD>澆<EFBFBD>銝<EFBFBD><E98A9D>硋龪<E7A18B>?(憒?"3cm" vs "3.0cm")
|
||
if (isNumber(valA) && isNumber(valB) && parse(valA) \=== parse(valB)) continue;
|
||
|
||
// 3\. (<28>舫<EFBFBD>? 霂凋<E99C82><E5878B>訾撮摨血龪<E8A180>?
|
||
// if (similarity(valA, valB) \> 0.95) continue;
|
||
|
||
conflicts.push(key);
|
||
}
|
||
|
||
return conflicts.length \=== 0 ? 'CLEAN' : 'CONFLICT';
|
||
}
|
||
|
||
## **4\. <20>唳旿摨栞挽霈?(Database Schema)**
|
||
|
||
V2 <20><>閬<EFBFBD><E996AC><EFBFBD>其舅隞?AI 蝏𤘪<E89D8F>隞亙<E99A9E><E4BA99>冽<EFBFBD><E586BD><EFBFBD><EFBFBD><EFBFBD>喟<EFBFBD><E5969F>栶<EFBFBD>?
|
||
### **Prisma Schema <20>湔鰵**
|
||
|
||
// 隞餃𦛚銵?
|
||
model ExtractionJob {
|
||
id String @id @default(uuid())
|
||
// ...<2E>嗡<EFBFBD>摮埈挾
|
||
diseaseType String // <20>曄<EFBFBD>蝐餃<E89D90> (<28>箇<EFBFBD>)
|
||
reportType String // <20>亙<EFBFBD>蝐餃<E89D90> (<28><><EFBFBD>)
|
||
targetFields Json // <20>格<EFBFBD>摮埈挾摰帋<E691B0> \[{name: "<22>輻𠈔憭批<E686AD>", desc: "..."}\]
|
||
}
|
||
|
||
// <20>閗<EFBFBD>霈啣<E99C88>銵?
|
||
model ExtractionItem {
|
||
id String @id @default(uuid())
|
||
jobId String
|
||
originalText String @db.Text
|
||
|
||
// V2 <20>詨<EFBFBD>摮埈挾
|
||
resultA Json? // DeepSeek 蝏𤘪<E89D8F> { "size": "3cm" }
|
||
resultB Json? // Qwen 蝏𤘪<E89D8F> { "size": "3.0 cm" }
|
||
|
||
// <20>脩<EFBFBD>璉<EFBFBD>瘚讠<E7989A><E8AEA0>?
|
||
status ItemStatus // PENDING, CLEAN, CONFLICT, RESOLVED
|
||
conflictFields String\[\] // \["size"\] 霈啣<E99C88><E595A3>芯<EFBFBD>摮埈挾<E59F88>脩<EFBFBD>鈭?
|
||
|
||
// <20><>蝏<EFBFBD><E89D8F>蝥喟<E89DA5><E5969F>?(<28>冽<EFBFBD>鋆<EFBFBD><E98B86><EFBFBD>𤾸<EFBFBD><F0A4BEB8>伐<EFBFBD><E4BC90>𤥁<EFBFBD><F0A4A581><EFBFBD><EFBFBD>湔𧒄<E6B994>芸𢆡<E88AB8>坔<EFBFBD>)
|
||
finalResult Json?
|
||
}
|
||
|
||
## **5\. <20>亙藁霈曇恣 (API Endpoints)**
|
||
|
||
### **5.1 璅∠<E79285>銝𡡞<E98A9D>蝵?*
|
||
|
||
* GET /api/templates: <20>瑕<EFBFBD>憸<EFBFBD>挽<EFBFBD><E68CBD>𪆴<EFBFBD><F0AA86B4><EFBFBD><EFBFBD>亙<EFBFBD>璅∠<E79285><E288A0>𡑒”<F0A19192>?
|
||
* POST /api/jobs: <20>𥕦遣隞餃𦛚嚗釶ayload 銝剝<E98A9D><E5899D><EFBFBD>鉄 diseaseType <20>?reportType嚗䔶噶鈭𤾸<E988AD>蝡舐<E89DA1>鋆?Prompt<70>?
|
||
### **5.2 蝵烐聢撉諹<E69289> (Grid Verification)**
|
||
|
||
* GET /api/jobs/:id/rows: <20><>△<EFBFBD>瑕<EFBFBD>撉諹<E69289><E8ABB9>唳旿<E594B3>?
|
||
* **Response:** 餈𥪜<E9A488> originalText, resultA, resultB, conflictFields<64>?
|
||
* POST /api/items/:id/resolve: <20>閗<EFBFBD>鋆<EFBFBD><E98B86><EFBFBD>?
|
||
* **Payload:** { field: "tumor\_size", chosenValue: "3cm" }<7D>?
|
||
* **Logic:** <20>湔鰵 finalResult嚗<74><E59A97><EFBFBD>𡏭砲銵峕<E98AB5><E5B395>匧<EFBFBD>蝒<EFBFBD><E89D92>畾菟<E795BE>撌脰圾<E884B0>喉<EFBFBD>撠?status <20>湔鰵銝?RESOLVED<45>?
|
||
## **6\. <20>滨垢霂衣<E99C82>霈曇恣 (Frontend)**
|
||
|
||
### **6.1 <20>冽艶撉諹<E69289>蝵烐聢 (Verification Grid)**
|
||
|
||
* **蝏<>辣<EFBFBD>匧<EFBFBD>嚗?* 靘萘<E99D98><E89098>刻<EFBFBD> **TanStack Table** (<28>餉<EFBFBD>撅? \+ **UI 蝏<>辣摨?* (皜脫<E79A9C>撅?<3F>?
|
||
* **<2A>脩<EFBFBD><E884A9>訫<EFBFBD><E8A8AB>潭葡<E6BDAD>橒<EFBFBD>**
|
||
* 敶?conflictFields.includes(column.id) <20>塚<EFBFBD><E5A19A>訫<EFBFBD><E8A8AB>潭葡<E6BDAD>㮖蛹**撖寞<E69296>璅∪<E79285>**<2A>?
|
||
* <20>曄內銝支葵撠𤩺<E692A0><F0A4A9BA>殷<EFBFBD>\[DS: 3cm\] <20>?\[QW: 3.0cm\]<5D>?
|
||
* <20>冽<EFBFBD><E586BD>孵稬隞颱<E99A9E><E9A2B1>厰僼嚗諹圻<E8ABB9>?resolve API嚗<49><E59A97>蝡臭<E89DA1>閫<EFBFBD>凒<EFBFBD>堆<EFBFBD>Optimistic Update嚗劐蛹<E58A90>劐葉<E58A90>嗆<EFBFBD><E59786><EFBFBD>?
|
||
### **6.2 靘扯器<E689AF>誩<EFBFBD><E8AAA9>?(Context Drawer)**
|
||
|
||
* **閫血<E996AB>嚗?* <20>孵稬銵冽聢銵𣬚<E98AB5>蝛箇蒾憭<E892BE><E686AD><EFBFBD>𨀣䰻<F0A880A3>见<EFBFBD><E8A781><EFBFBD><EFBFBD>嘥㦛<E598A5><E3A69B><EFBFBD>?
|
||
* **<2A>蠘<EFBFBD>嚗?* 撅閧內 originalText<78>?
|
||
* **擃䀝漁隡睃<E99AA1>嚗?* 蝞<><E89D9E>訫<EFBFBD><E8A8AB>?String.indexOf <20>交𪄳敶枏<E695B6>摮埈挾<E59F88><E68CBE><EFBFBD>澆僎<E6BE86><E5838E><EFBFBD><EFBFBD>?
|
||
## **7\. 憌𡡞埯<F0A1A19E>批<EFBFBD>銝擧<E98A9D>扯<EFBFBD>隡睃<E99AA1>**
|
||
|
||
| 瞏𨅯銁憌𡡞埯 | 閫<><E996AB><EFBFBD>寞<EFBFBD> |
|
||
| :---- | :---- |
|
||
| **<EFBFBD><EFBFBD><EFBFBD>?Token <20>鞉𧋦** | 1\. 暺䁅恕雿輻鍂 DeepSeek (<28><><EFBFBD><EFBFBD>鞉𧋦) \+ Qwen (雿擧<E99BBF><E693A7>? 蝏<><E89D8F><EFBFBD>?2\. <20>兩<EFBFBD>靝<EFBFBD>璉<EFBFBD><E79289>嗪𧫴畾萎艇<E8908E>潭㜃<E6BDAD>芣<EFBFBD><E88AA3><EFBFBD>㺭<EFBFBD>柴<EFBFBD>?|
|
||
| **憭<><E686AD><EFBFBD>笔漲<E7AC94>?* | 銝支葵璅∪<E79285>敹<EFBFBD>◆ **撟嗅<E6929F>靚<EFBFBD>鍂 (Promise.all)**嚗諹<E59A97>䔶<EFBFBD><E494B6>臭葡銵䎚<E98AB5><E48E9A>㟲雿栞<E99BBF>埈𧒄<E59F88>硋<EFBFBD>鈭擧<E988AD><E693A7>Y<EFBFBD><EFBCB9><EFBFBD>葵璅∪<E79285><E288AA>?|
|
||
| **璅∪<E79285><E288AA>澆<EFBFBD>銝滚𨯬霂?* | Prompt 銝剖<E98A9D><E58996>?Few-Shot (撠烐甅<E78390>? 蝷箔<E89DB7>嚗峕<E59A97>蝖桀<E89D96>蝷?JSON <20>澆<EFBFBD><E6BE86><EFBFBD><EFBFBD><EFBFBD>?JSON 閫<><E996AB>憭梯揖嚗諹䌊<E8ABB9>券<EFBFBD>霂?1 甈~<E79488>?|
|
||
| **<EFBFBD>滨垢蝵烐聢<EFBFBD>⊿▼** | 憒<><E68692><EFBFBD>唳旿頞<E697BF><E9A09E> 1000 <20>∴<EFBFBD>撘<EFBFBD><E69298>?Virtual Scrolling (<28>𡁏<EFBFBD>皛𡁜𢆡)<29>?|
|
||
|