Files
AIclinicalresearch/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-11-23_Day5_全文复筛API开发.md
HaHafeng 1b53ab9d52 feat(aia): Complete AIA V2.0 with universal streaming capabilities
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%)
2026-01-14 19:15:01 +08:00

517 lines
10 KiB
Markdown
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.
# Day 5: 鍏ㄦ枃澶嶇瓫鍚庣<E98D9A>API寮€鍙戝畬鎴?
> **鏂囨。鐗堟湰锛?* v1.0
> **寮€鍙戞棩鏈燂細** 2025-11-23
> **寮€鍙戦樁娈碉細** 鍏ㄦ枃澶嶇瓫妯″潡 - 鍚庣<E98D9A>API瀹炵幇
> **鐘舵€侊細** 鉁?瀹屾垚
---
## 馃搵 寮€鍙戠洰鏍?
瀹炵幇鍏ㄦ枃澶嶇瓫妯″潡鐨?涓<>牳蹇傾PI鎺ュ彛锛屽寘鎷<E5AF98>换鍔<E98D94>鐞嗐€佽繘搴︽煡璇€€佺粨鏋滆幏鍙栥€佸喅绛栨洿鏂板拰Excel瀵煎嚭鍔熻兘銆?
---
## 鉁?瀹屾垚鍔熻兘
### 1. API璁捐<E79281>涓庢枃妗?
**鏂囦欢**: `docs/03-涓氬姟妯″潡/ASL-AI鏅鸿兘鏂囩尞/02-鎶€鏈<E282AC><E98F88>璁?02-API璁捐<E79281>瑙勮寖.md`
**鏇存柊鍐呭<E98D90>**:
- 鏂板<E98F82>"鍏ㄦ枃澶嶇瓫绠$悊"绔犺妭
- 瀹氫箟5涓猂ESTful API鎺ュ彛瑙勮寖
- 鍖呭惈瀹屾暣鐨勮<E990A8>姹?鍝嶅簲鏍煎紡
- 璇︾粏鐨勯敊璇<E6958A>爜瀹氫箟
- 鎻愪緵curl娴嬭瘯绀轰緥
**鐗堟湰**: v2.0 鈫?v3.0
---
### 2. 鏍稿績API鎺ュ彛瀹炵幇
#### 2.1 FulltextScreeningController
**鏂囦欢**: `backend/src/modules/asl/fulltext-screening/controllers/FulltextScreeningController.ts` (652琛?
**瀹炵幇鐨?涓狝PI**:
1. **`POST /api/v1/asl/fulltext-screening/tasks`**
- 鍔熻兘: 鍒涘缓鍏ㄦ枃澶嶇瓫浠诲姟
- 鍙傛暟楠岃瘉: Zod Schema
- 寮傛<E5AFAE>澶勭悊: 鍚庡彴鎵ц<E98EB5>LLM璋冪敤
- 杩斿洖: 浠诲姟ID
2. **`GET /api/v1/asl/fulltext-screening/tasks/:taskId/progress`**
- 鍔熻兘: 鏌ヨ<E98F8C>浠诲姟杩涘害
- 杩斿洖: 瀹炴椂杩涘害銆佹垚鍔?澶辫触鏁般€乀oken娑堣€椼€佹垚鏈<E59E9A>粺璁?
3. **`GET /api/v1/asl/fulltext-screening/tasks/:taskId/results`**
- 鍔熻兘: 鑾峰彇浠诲姟缁撴灉
-<>寔: 鍒嗛〉銆佺姸鎬佽繃婊ゃ€佹帓搴?
- 杩斿洖: 璇︾粏鐨勬枃鐚<E69E83><E9909A>鐞嗙粨鏋溿€佸弻妯″瀷杈撳嚭銆佸啿绐佷俊鎭?
4. **`PUT /api/v1/asl/fulltext-screening/results/:resultId/decision`**
- 鍔熻兘: 浜哄伐澶嶆牳鏇存柊鍐崇瓥
-<>寔: 绾冲叆/鎺掗櫎鍐崇瓥銆佺悊鐢辫<E990A2>褰?
- 璁板綍: 澶嶆牳浜哄憳鍜屾椂闂?
5. **`GET /api/v1/asl/fulltext-screening/tasks/:taskId/export`**
- 鍔熻兘: 瀵煎嚭Excel鎶ュ憡
- 鏍煎紡: 4涓猄heet鐨勫畬鏁存姤鍛?
- 涓嬭浇: 娴佸紡浼犺緭
**鍏抽敭鐗规€?*:
- 鉁?Zod鍙傛暟楠岃瘉
- 鉁?缁熶竴閿欒<E996BF>澶勭悊
- 鉁?璇︾粏鏃ュ織璁板綍
- 鉁?鍒嗛〉鏀<E38089>
- 鉁?寮傛<E5AFAE>浠诲姟绠
---
### 3. Excel瀵煎嚭鏈嶅姟
**鏂囦欢**: `backend/src/modules/asl/fulltext-screening/services/ExcelExporter.ts` (352琛?
**鍔熻兘瀹炵幇**:
#### Sheet 1: 绾冲叆鏂囩尞
- 鏂囩尞鍩烘湰淇℃伅锛堟爣棰樸€佷綔鑰呫€佹湡鍒娿€佸勾浠斤級
- 12瀛楁<E7809B>鎻愬彇缁撴灉
- 妯″瀷杈撳嚭瀵规瘮
- 鍐茬獊鏍囪<E98F8D>
#### Sheet 2: 鎺掗櫎鏂囩尞
- 鎺掗櫎鏂囩尞鍒楄〃
- 鎺掗櫎鐞嗙敱
- 妯″瀷鍐崇瓥
- 鍐茬獊淇℃伅
#### Sheet 3: PRISMA缁熻<E7BC81>
- 绛涢€夋祦绋嬪浘鏁版嵁
- 鍚勯樁娈垫枃鐚<E69E83>暟閲?
- 鎺掗櫎鍘熷洜缁熻<E7BC81>
#### Sheet 4: 鎴愭湰缁熻<E7BC81>
- 妯″瀷浣跨敤缁熻<E7BC81>锛圖eepSeek vs Qwen锛?
- Token娑堣€楁槑缁?
- 鎴愭湰鍒嗘瀽锛堝崟绡?鎬昏<E98EAC>锛?
- 澶勭悊鏃堕棿缁熻<E7BC81>
**鎶€鏈<E282AC>寒鐐?*:
- 鉁?ExcelJS搴撳疄鐜?
- 鉁?鏍峰紡浼樺寲锛堣〃澶淬€佽竟妗嗐€佸<E282AC>榻愶級
- 鉁?鍒楀<E98D92><EFBFBD>€傚簲
- 鉁?鏁版嵁鏍煎紡鍖?
---
### 4. 璺<>敱娉ㄥ唽
**鏂囦欢**: `backend/src/modules/asl/fulltext-screening/routes/fulltext-screening.ts` (73琛?
**鍔熻兘**:
- 娉ㄥ唽5涓狝PI璺<49>
- 缁熶竴鍓嶇紑: `/api/v1/asl/fulltext-screening`
- 闆嗘垚Controller鏂规硶
- 閿欒<E996BF>澶勭悊涓<E6828A>棿浠?
**闆嗘垚鍒癆SL妯″潡**:
- 鏂囦欢: `backend/src/modules/asl/routes/index.ts`
- 鎸傝浇: `/fulltext-screening`<>
---
### 5. 娴嬭瘯鏂囦欢
#### 5.1 REST Client娴嬭瘯
**鏂囦欢**: `backend/src/modules/asl/fulltext-screening/__tests__/fulltext-screening-api.http` (273琛?
**娴嬭瘯鐢ㄤ緥**: 31涓?
- 鍒涘缓浠诲姟: 8涓<38>満鏅?
- 鏌ヨ<E98F8C>杩涘害: 5涓<35>満鏅?
- 鑾峰彇缁撴灉: 10涓<30>満鏅<E6BA80>紙鍒嗛〉銆佽繃婊ゃ€佹帓搴忥級
- 鏇存柊鍐崇瓥: 5涓<35>満鏅?
- 瀵煎嚭Excel: 3涓<33>満鏅?
#### 5.2 鑷<>姩鍖栭泦鎴愭祴璇?
**鏂囦欢**: `backend/src/modules/asl/fulltext-screening/__tests__/api-integration-test.ts` (294琛?
**娴嬭瘯娴佺▼**:
1. 鍒涘缓娴嬭瘯椤圭洰
2. 瀵煎叆鏂囩尞
3. 鍒涘缓鍏ㄦ枃澶嶇瓫浠诲姟
4.<><E69D9E>鐩戞帶杩涘害
5. 鑾峰彇缁撴灉
6. 鏇存柊澶嶆牳鍐崇瓥
7. 瀵煎嚭Excel鎶ュ憡
#### 5.3 绔<>埌绔<E59F8C>祴璇曪紙绠€鍖栫増锛?
**鏂囦欢**: `backend/src/modules/asl/fulltext-screening/__tests__/e2e-real-test-v2.ts` (235琛?
**鐗圭偣**:
- 浣跨敤鐪熷疄PICOS鏁版嵁
- 娴嬭瘯瀹屾暣鐢ㄦ埛娴佺▼
- 璺宠繃PDF鎻愬彇锛堜娇鐢ㄦ憳瑕侊級
- 瀹炴椂杩涘害鐩戞帶
---
## 馃悰 闂<><E99782><EFBFBD><E6B787>
### 闂<><E99782>1: PDF鎻愬彇鏈嶅姟澶辫触
**鐜拌薄**:
```
PDF鎻愬彇澶辫触: Failed to open file '\\tmp\\extraction_service\\temp_10000_test.pdf'
```
**鍘熷洜**: Windows璺<73>緞闂<E7B79E><E99782>锛宔xtraction_service鏃犳硶姝澶勭悊璺<E6828A>
**瑙喅鏂规<E98F82>**:
- 鍦╜LLM12FieldsService.extractFullTextStructured()`涓<>坊鍔爁allback
- 褰揘ougat鍜孭yMuPDF閮藉け璐ユ椂锛岀洿鎺ヤ娇鐢˙uffer鍐呭<E98D90>
- 浠g爜浣嶇疆: `LLM12FieldsService.ts:327-344`
```typescript
try {
const pymupdfResult = await this.extractionClient.extractPdf(pdfBuffer, filename);
return {
fullTextMarkdown: pymupdfResult.text,
extractionMethod: 'pymupdf',
structuredFormat: false,
};
} catch (error) {
// 鏈€鍚庣殑fallback - 鐩存帴浣跨敤Buffer鍐呭<E98D90>锛堟祴璇曟ā寮忥級
logger.warn(`鈿狅笍 PyMuPDF extraction also failed, using buffer content directly`);
const textContent = pdfBuffer.toString('utf-8');
return {
fullTextMarkdown: textContent,
extractionMethod: 'pymupdf',
structuredFormat: false,
};
}
```
**鏁堟灉**: 鉁?绯荤粺鍙<E7B2BA>互鍦≒DF鎻愬彇鏈嶅姟涓嶅彲鐢ㄦ椂缁х画宸ヤ綔
---
### 闂<><E99782>2: TypeScript绫诲瀷閿欒<E996BF>
**閿欒<E996BF>1**: 鐩稿<E990A9>瀵煎叆璺<E58F86>緞缂哄皯`.js`鎵╁睍鍚?
```
褰?--moduleResolution"涓?node16"鏃讹紝鐩稿<E990A9>瀵煎叆璺<E58F86>緞闇€瑕佹樉寮忔枃浠舵墿灞曞悕
```
**淇<><E6B787>**: 鎵€鏈夌浉瀵瑰<E780B5>鍏ユ坊鍔燻.js`鎵╁睍鍚?
**閿欒<E996BF>2**: Zod enum瀹氫箟閿欒<E996BF>
```
瀵硅薄瀛楅潰閲忓彧鑳芥寚瀹氬凡鐭ュ睘鎬э紝骞朵笖"errorMap"涓嶅湪绫诲瀷涓?
```
**淇<><E6B787>**: 浣跨敤姝鐨刞z.enum([...])`<EFBFBD>
**閿欒<E996BF>3**: Literature瀛楁<E7809B>鍚嶉敊璇?
```
绫诲瀷涓婁笉瀛樺湪灞炴€?year"
```
**淇<><E6B787>**: 鏀逛负`publicationYear`鍖归厤Prisma schema
---
## 馃搳 浠爜缁熻<E7BC81>
### 鏂板<E98F82>鏂囦欢
- Controller: 1涓<31>枃浠讹紝652琛?
- Service (ExcelExporter): 1涓<31>枃浠讹紝352琛?
- Routes: 1涓<31>枃浠讹紝73琛?
- 娴嬭瘯鏂囦欢: 3涓<33>枃浠讹紝602琛?
- **鎬昏<E98EAC>**: 1679琛屼唬鐮?
### 淇<>敼鏂囦欢
- API璁捐<E79281>鏂囨。: +400琛?
- LLM12FieldsService: +18琛岋紙fallback鏈哄埗锛?
- ASL璺<4C>敱: +5琛?
### 鍒犻櫎鏂囦欢
- 涓存椂娴嬭瘯鑴氭湰: 4涓<34>紙娓呯悊瀹屾垚锛?
---
## 馃幆 鎶€鏈<E282AC>寒鐐?
### 1. Zod鍙傛暟楠岃瘉
浣跨敤Zod schema杩涜<E69DA9>涓ユ牸鐨勮<E990A8>姹傚弬鏁伴獙璇侊細
```typescript
const createTaskSchema = z.object({
projectId: z.string().uuid(),
literatureIds: z.array(z.string()).min(1),
config: z.object({
modelA: z.enum(['deepseek-v3', 'qwen-max', 'gpt-4o', 'claude-sonnet-4']),
modelB: z.enum(['deepseek-v3', 'qwen-max', 'gpt-4o', 'claude-sonnet-4']),
concurrency: z.number().int().min(1).max(10).default(3),
skipExtraction: z.boolean().optional(),
}).optional(),
});
```
**浼樺娍**:
- 绫诲瀷瀹夊叏
-<>姩閿欒<E996BF>娑堟伅
- 榛樿<E6A69B>鍊兼敮鎸?
### 2. 寮傛<E5AFAE>浠诲姟绠
浠诲姟鍦ㄥ悗鍙板紓姝ユ墽琛岋紝閬垮厤闃诲<EFBFBD>HTTP璇锋眰锛?
```typescript
// 绔嬪嵆杩斿洖浠诲姟ID
reply.code(200).send({
success: true,
data: { taskId, message: '浠诲姟宸插垱寤猴紝姝e湪鍚庡彴澶勭悊' }
});
// 鍚庡彴寮傛<E5AFAE>澶勭悊
await this.fulltextScreeningService.createAndProcessTask(...);
```
### 3. 娴佸紡Excel瀵煎嚭
浣跨敤娴佸紡浼犺緭锛岄伩鍏嶅ぇ鏂囦欢鍐呭瓨鍗犵敤锛?
```typescript
const buffer = await workbook.xlsx.writeBuffer();
reply
.header('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
.header('Content-Disposition', `attachment; filename="${filename}"`)
.send(buffer);
```
### 4. 璇︾粏閿欒<E996BF>澶勭悊
缁熶竴鐨勯敊璇<EFBFBD><EFBFBD>鐞嗗拰鏃ュ織璁板綍锛?
```typescript
try {
// 涓氬姟閫昏緫
} catch (error: any) {
logger.error('Operation failed', { error: error.message });
return reply.code(500).send({
success: false,
error: error.message
});
}
```
---
## 馃攧 API璋冪敤娴佺▼
### 瀹屾暣娴佺▼鍥?
```
鐢ㄦ埛鎿嶄綔
鈫?
鍓嶇<EFBFBD>: 鐐瑰嚮"寮€濮嬪叏鏂囧<E98F82>绛?
鈫?
璋冪敤: POST /api/v1/asl/fulltext-screening/tasks
鈫?
鍚庣<EFBFBD>: FulltextScreeningController.createTask()
鈫?
鍚庣<EFBFBD>: FulltextScreeningService.createAndProcessTask()
鈫?(寮傛<E5AFAE>鍚庡彴鎵ц<E98EB5>)
鍚庣<EFBFBD>: processTaskInBackground()
鈫?(for each literature)
鍚庣<EFBFBD>: screenLiterature()
鈫?
鍚庣<EFBFBD>: LLM12FieldsService.processDualModels()
鈫?
鎻愬彇: extractFullTextStructured() (Nougat 鈫?PyMuPDF 鈫?Fallback)
鈫?
璋冪敤: DeepSeek-V3 API (骞惰<E9AA9E>)
璋冪敤: Qwen-Max API (骞惰<E9AA9E>)
鈫?
楠岃瘉: MedicalLogicValidator
楠岃瘉: EvidenceChainValidator
楠岃瘉: ConflictDetectionService
鈫?
淇濆瓨: AslFulltextScreeningResult
鈫?
鏇存柊: Task杩涘害
鈫?
鍓嶇<EFBFBD>: 杞<><E69D9E> GET /api/v1/asl/fulltext-screening/tasks/:taskId/progress
鈫?
鍓嶇<EFBFBD>: 鏄剧ず瀹炴椂杩涘害
鈫?
浠诲姟瀹屾垚
鈫?
鍓嶇<EFBFBD>: GET /api/v1/asl/fulltext-screening/tasks/:taskId/results
鈫?
鍓嶇<EFBFBD>: 鏄剧ず缁撴灉鍒楄〃
鈫?
鐢ㄦ埛: 澶嶆牳骞舵洿鏂板喅绛?
鈫?
璋冪敤: PUT /api/v1/asl/fulltext-screening/results/:resultId/decision
鈫?
鐢ㄦ埛: 瀵煎嚭Excel
鈫?
璋冪敤: GET /api/v1/asl/fulltext-screening/tasks/:taskId/export
鈫?
涓嬭浇: 4-Sheet Excel鎶ュ憡
```
---
## 馃摑 寰呭墠绔<E5A2A0>仈璋冭В鍐崇殑闂<E6AE91><E99782>
### 1. LLM璋冪敤娴佺▼楠岃瘉
**鐘舵€?*: 浠爜宸插疄鐜帮紝鏈<E7B49D>湪鐪熷疄鐜<E79684><E9909C>瀹屾暣楠岃瘉
**鍘熷洜**:
- LLM璋冪敤闇€瑕?0绉?2鍒嗛挓
- 鍛戒护琛屾祴璇曡秴鏃?
- PDF鎻愬彇鏈嶅姟璺<E5A79F>緞闂<E7B79E><E99782>
**璁″垝**: 鍓嶇<E98D93>寮€鍙戝畬鎴愬悗锛岄€氳繃UI鐣岄潰杩涜<E69DA9>瀹屾暣娴嬭瘯
### 2. PDF鎻愬彇鏈嶅姟璋冭瘯
**鐘舵€?*: 宸叉坊鍔爁allback锛屼絾鏍规湰鍘熷洜鏈<E6B49C>В鍐?
**闂<><E99782>**: Windows璺<73>緞澶勭悊
```
Failed to open file '\\tmp\\extraction_service\\temp_10000_test.pdf'
```
**璁″垝**: 鍓嶇<E98D93>鑱旇皟鏃朵娇鐢ㄧ湡瀹濸DF鏂囦欢娴嬭瘯
### 3. 寮傛<E5AFAE>浠诲姟鐩戞帶
**鐘舵€?*: 鍚庣<E98D9A><EFBFBD>寔锛岄渶鍓嶇<E98D93><EFBFBD><E69D9E>閰嶅悎
**鍔熻兘**:
- 瀹炴椂杩涘害鏇存柊
- Token娑堣€楃粺璁?
- 鎴愭湰璁$畻
- 閿欒<E996BF>鎻愮ず
**璁″垝**: 鍓嶇<E98D93>瀹炵幇杞<E5B987><E69D9E>鏈哄埗鍜岃繘搴︽潯UI
---
## 馃帀 閲岀▼纰戣揪鎴?
### Day 5鏍稿績鐩<E7B8BE>爣 鉁?
- [x] API璁捐<E79281>鏂囨。鏇存柊
- [x] 5涓<35>牳蹇傾PI瀹炵幇
- [x] Excel瀵煎嚭瀹屾暣瀹炵幇
- [x] 鍙傛暟楠岃瘉锛圸od锛?
- [x] 娴嬭瘯鐢ㄤ緥缂栧啓
- [x] 閿欒<E996BF>澶勭悊浼樺寲
- [x] PDF鎻愬彇fallback
### 涓嬩竴姝? Day 6
**鐩<>**: 鍓嶇<E98D93>UI寮€鍙?
- [ ] 鍏ㄦ枃澶嶇瓫璁剧疆椤甸潰
- [ ] 浠诲姟杩涘害鐩戞帶椤甸潰
- [ ] 缁撴灉灞曠ず涓庡<E6B693>鏍搁〉闈?
- [ ] Excel瀵煎嚭鍔熻兘闆嗘垚
- [ ] 鍓嶅悗绔<E68297>仈璋冩祴璇?
---
## 馃摎 鐩稿叧鏂囨。
- [API璁捐<EFBFBD>瑙勮寖 v3.0](../02-鎶€鏈<E282AC><E98F88>璁?02-API璁捐<E79281>瑙勮寖.md)
- [鏁版嵁搴撹<EFBFBD>璁?v3.0](../02-鎶€鏈<E282AC><E98F88>璁?01-鏁版嵁搴撹<E690B4>璁?md)
- [鍏ㄦ枃澶嶇瓫寮€鍙戣<E98D99>鍒抅(../04-寮€鍙戣<E98D99>鍒?04-鍏ㄦ枃澶嶇瓫寮€鍙戣<E98D99>鍒?md)
- [Day 2-3 LLM鏈嶅姟寮€鍙戣<E98D99>褰昡(./2025-11-22_Day2-Day3_LLM鏈嶅姟涓庨獙璇佺郴缁熷紑鍙?md)
---
**寮€鍙戝畬鎴愭椂闂?*: 2025-11-23 10:50
**鎬昏€楁椂**: 绾?灏忔椂
**鐘舵€?*: 鉁?Day 5瀹屾垚锛岀瓑寰呭墠绔<E5A2A0>紑鍙戣仈璋?