Files
AIclinicalresearch/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_MVP开发计划_V1.0.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

67 KiB
Raw Blame History

宸ュ叿C - 绉戠爺鏁版嵁缂栬緫鍣?MVP寮€鍙戣<E98D99>鍒?

*鏂囨。鐗堟湰锛? V1.0 (鍔″疄蹇<E79684>€熼獙璇佺増)
*鍒涘缓鏃ユ湡锛? 2025-12-06
*璁″垝鍛ㄦ湡锛? 3鍛<33>紙15涓<35>伐浣滄棩锛? *鏍稿績绛栫暐锛? 鐢ㄦ渶灏忔垚鏈<E59E9A>獙璇佹牳蹇冨亣璁撅紝蹇<E7B49D>€熷け璐ヤ紭浜庡畬缇庤<E7BC87>鍒? 鐘舵€侊細 寰呭惎鍔?


鈿狅笍 寮€鍙戝墠蹇呰<E8B987>锛氫弗鏍奸伒瀹堢幇鏈夋灦鏋勪笌瑙勮寖

馃敶 涓嶈<E6B693>閲嶅<E996B2>閫犺疆瀛愶紒澶嶇敤骞冲彴鑳藉姏

<EFBFBD>」鐩<EFBFBD>凡鏈夊畬鏁寸殑3灞傛灦鏋勪綋绯诲拰骞冲彴鍩虹<EFBFBD>璁炬柦锛屾墍鏈変唬鐮佸繀椤诲<EFBFBD>鐢ㄧ幇鏈夎兘鍔涳細

骞冲彴鍩虹<EFBFBD>灞傦紙鉁?宸插畬鎴愶紝鐩存帴浣跨敤锛?

鏈嶅姟 瀵煎叆鏂瑰紡 鐢ㄩ€? 鏂囨。
瀛樺偍鏈嶅姟 import { storage } from '@/common/storage' 鏂囦欢涓婁紶涓嬭浇 鉁?蹇呴』浣跨敤
鏃ュ織绯荤粺 import { logger } from '@/common/logging' 鏍囧噯鍖栨棩蹇? 鉁?蹇呴』浣跨敤
缂撳瓨鏈嶅姟 import { cache } from '@/common/cache' 鍒嗗竷寮忕紦瀛? 鉁?蹇呴』浣跨敤
寮傛<EFBFBD>浠诲姟 import { jobQueue } from '@/common/jobs' 闀挎椂闂翠换鍔? 鉁?蹇呴』浣跨敤
*鏁版嵁搴? import { prisma } from '@/config/database' 鏁版嵁搴撴搷浣? 鉁?蹇呴』浣跨敤
LLM鑳藉姏 import { LLMFactory } from '@/common/llm' LLM璋冪敤 鉁?蹇呴』浣跨敤

浜戝師鐢熷紑鍙戣<EFBFBD>鑼冿紙鉁?寮哄埗鎵ц<E98EB5>锛?

**璇︾粏鏂囨。**锛歚docs/04-寮€鍙戣<E98D99>鑼?08-浜戝師鐢熷紑鍙戣<E98D99>鑼?md`

*鏍稿績瑕佹眰锛?

  • 鉁?鏂囦欢瀛樺偍锛氫娇鐢╜storage.upload()锛屼笉瑕佺敤fs.writeFile()`
  • 鉁?Session绠锛氬瓨鏁版嵁搴擄紝涓嶈<EFBFBD>鐢╜Map<sessionId, data>`
  • 鉁?鏃ュ織杈撳嚭锛氫娇鐢╜logger.info()锛屼笉瑕佺敤console.log()`
  • 鉁?**鏁版嵁搴撹繛鎺?*锛氫娇鐢ㄥ叏灞€prisma瀹炰緥锛屼笉瑕乣new PrismaClient()`
  • 鉁?LLM璋冪敤锛氫娇鐢╜LLMFactory.getLLM()`锛屼笉瑕佽嚜宸遍泦鎴?
  • 鉂?绂佹<EFBFBD><EFBFBD>湴鏂囦欢瀛樺偍锛欵xcel鐩存帴浠庡唴瀛樿В鏋?
  • 鉂?绂佹<EFBFBD>鍐呭瓨缂撳瓨Map锛氱敤鏁版嵁搴撴垨cache鏈嶅姟
  • 鉂?**绂佹<E7BB82><EFBFBD>紪鐮侀厤缃?*锛氫娇鐢ㄧ幆澧冨彉閲?

浠g爜鏂囦欢澶圭粨鏋勶紙鉁?鍙傝€僼ool-b锛?

**鍚庣<E98D9A>**锛?

backend/src/modules/dc/tool-c/        鈫?宸插瓨鍦?
鈹溾攢鈹€ services/                          鈫?涓氬姟閫昏緫
鈹溾攢鈹€ controllers/                       鈫?HTTP鎺у埗鍣?
鈹溾攢鈹€ routes/                            鈫?璺<>敱瀹氫箟
鈹斺攢鈹€ utils/                             鈫?宸ュ叿鍑芥暟

**鍓嶇<E98D93>**锛?

frontend-v2/src/modules/dc/pages/tool-c/  鈫?宸插瓨鍦?

甯歌<EFBFBD>閿欒<EFBFBD>绀轰緥锛堚潓 涓ョ<E6B693>锛?

// 鉂?閿欒<E996BF>1锛氳嚜宸卞疄鐜癝ession绠const sessions = new Map<string, any>();  // 杩濆弽瑙勮寖锛?

// 鉂?閿欒<E996BF>2锛氭湰鍦版枃浠跺瓨鍌?
fs.writeFileSync('./uploads/file.xlsx', buffer);  // 杩濆弽瑙勮寖锛?

// 鉂?閿欒<E996BF>3锛氫笉鐢╨ogger
console.log('User uploaded file');  // 杩濆弽瑙勮寖锛?

// 鉂?閿欒<E996BF>4锛氭柊寤篜risma瀹炰緥
const prisma = new PrismaClient();  // 杩濆弽瑙勮寖锛?

// 鉂?閿欒<E996BF>5锛氳嚜宸遍泦鎴怢LM
import Anthropic from '@anthropic-ai/sdk';  // 杩濆弽瑙勮寖锛?

**姝g‘绀轰緥锛堚渽 蹇呴』锛?*锛氬弬鑰冩湰鏂囨。Day 1-5鐨勪唬鐮佺ず渚?


馃搵 鐩<>


涓€銆丮VP鏍稿績鐩<EFBFBD>

1.1 鏍稿績鍋囪<E98D8B>楠岃瘉

鎴戜滑闇€瑕侀獙璇佺殑3涓<EFBFBD>牳蹇冨亣璁撅細

鍋囪<EFBFBD> 楠岃瘉鏂瑰紡 鎴愬姛鏍囧噯 澶辫触鍚庢灉
*H1: AI鑳界敓鎴愰珮璐ㄩ噺Pandas浠爜骞舵垚鍔熸墽琛? 15涓<EFBFBD>湡瀹炲満鏅<EFBFBD>祴璇? 鎬讳綋鎴愬姛鐜?> 80% MVP澶辫触锛屾敼鐢ㄤ唬鐮佹ā鏉垮簱
H2: Python浠爜鎵ц<E98EB5><EFBFBD><E9909C>绋冲畾鍙<E795BE> 澶嶆潅鍦烘櫙娴嬭瘯 楂樼骇鍦烘櫙鎴愬姛鐜?> 60% 绠€鍖栦负鎵瑰<EFBFBD>鐞嗘ā寮?
*H3: 宸﹁〃鏍?鍙矨I鐨勪氦浜掓ā寮忓ソ鐢? 鐢ㄦ埛浣撻獙娴嬭瘯 鐢ㄦ埛鑳界嫭绔嬪畬鎴愪换鍔? 閲嶆柊璁捐<EFBFBD>UI浜や簰
*H4: 鎬ц兘鍙<E58598>帴鍙楋紙鍚玃ython鎵ц<E98EB5>锛? 鎬ц兘娴嬭瘯 <EFBFBD>埌绔?< 20绉? 浼樺寲Python鎵ц<EFBFBD>鎴栨敼鎵瑰<EFBFBD>鐞?

鈿狅笍 鏍稿績浠峰€间富寮狅細

  • 鉁?AI鐢熸垚浠爜 + 鐪熷疄鎵ц<E98EB5> + 琛ㄦ牸鍒锋柊<EFBFBD>伐鍏稢鐨勫樊寮傚寲浠峰€?
  • 鉁?濡傛灉鍙<E78189>敓鎴愪唬鐮佷笉鎵ц<E98EB5>锛岀敤鎴疯繕涓嶅<E6B693>鐩存帴鐢hatGPT
  • 鉁?Python鎵ц<E98EB5><EFBFBD><E9909C>鏄疢VP鐨?*鎶€鏈<E282AC>牳蹇?*锛屼笉鏄<E7AC89>彲閫夐」

1.2 MVP鍔熻兘鑼冨洿

鉁?MVP蹇呴』鏈夌殑锛圥0锛夛細

  1. 鏂囦欢涓婁紶锛?0MB闄愬埗锛?
  2. 琛ㄦ牸灞曠ず锛圓G Grid锛?00琛岄<E7909B>瑙堬級
  3. AI瀵硅瘽鐣岄潰锛堝彸渚т晶杈规爮锛?
  4. AI浠爜鐢熸垚锛圖eepSeek-V3锛?
  5. 爜鎵ц<EFBFBD>锛圥ython娌欑<EFBFBD>锛?
  6. UI閿佸畾鏈哄埗锛圓I澶勭悊鏃惰〃鏍煎彧璇伙級
  7. AST瀹夊叏妫€鏌?
  8. 琛ㄦ牸鑷<EFBFBD>姩鍒锋柊
  9. 瀵煎嚭Excel

鉂?MVP鏄庣涓嶅仛鐨勶細

  • 鎵嬪姩缂栬緫鍗曞厓鏍硷紙涓撴敞AI鑳藉姏锛?
  • 鎾ら攢/鍥炴粴锛堣妭鐪佸唴瀛橈級
  • Apache Arrow锛堝厛鐢↗SON锛?
  • Redis浼氳瘽锛堢敤杩涚▼鍐呭瓨锛?
  • 鏍峰紡淇濈暀锛堢洿鎺ヨ<EFBFBD>鐩栵級
  • 鎿嶄綔瀹¤<EFBFBD>鏃ュ織
  • 鍗忓悓缂栬緫

1.3 MVP浜や粯鐗?

鏈€缁堟紨绀哄満鏅<EFBFBD>

鐢ㄦ埛涓婁紶 "lung_cancer_patients.xlsx" (5000琛?脳 20鍒?
  鈫?
宸︿晶鏄剧ず鏁版嵁琛ㄦ牸锛屽彸渚<E5BDB8>I鍔╂墜鍑嗗<E98D91>灏辩华
  鈫?
鐢ㄦ埛瀵笰I璇达細"鎶婂勾榫勫ぇ浜?0鐨勬偅鑰呮爣璁颁负鑰佸勾缁?
  鈫?
AI鐢熸垚浠爜 鈫?灞曠ず棰勬搷浣滃崱鐗?鈫?鐢ㄦ埛纭<E59F9B><E7BAAD> 鈫?鎵ц<E98EB5>鎴愬姛
  鈫?
琛ㄦ牸鑷<E789B8>姩鍒锋柊锛屾柊澧?age_group"鍒?
  鈫?
鐢ㄦ埛缁х画璇达細"鍒犻櫎鎵€鏈夌己澶辨偅鑰匢D鐨勮<E990A8>"
  鈫?
AI鎵ц<E98EB5> 鈫?琛ㄦ牸鍒锋柊锛屾樉绀哄垹闄や簡23琛?
  鈫?
鐢ㄦ埛鐐瑰嚮"瀵煎嚭"锛屼笅杞藉<E69D9E>鐞嗗悗鐨凟xcel

*鎴愬姛鏍囧噯锛?

  • 鉁?鏁翠釜娴佺▼ < 2鍒嗛挓瀹屾垚
  • 鉁?AI浠爜涓€娆℃€ф墽琛屾垚鍔?
  • 鉁?鐢ㄦ埛鏃犻渶鐪嬫枃妗e氨鑳芥搷浣?

浜屻€佹妧鏈<EFBFBD>灦鏋勬柟妗堬紙鍔″疄鐗堬級

2.1 鎬讳綋鏋舵瀯锛堢畝鍖栫増锛? 鈿狅笍 閲嶈<E996B2>锛氬<E9949B>鐢ㄥ钩鍙拌兘鍔?

鈹屸攢鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹?
鈹?                   鍓嶇<E98D93> (React)                          鈹?
鈹? frontend-v2/src/modules/dc/pages/tool-c/               鈹?
鈹? 鈹屸攢鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹? 鈹屸攢鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹? 鈹?
鈹? 鈹?AG Grid (70%)        鈹? 鈹?AI Chat Sidebar (30%) 鈹? 鈹?
鈹? 鈹?鈥?灞曠ず100琛屾暟鎹?     鈹? 鈹?鈥?鑷<>劧璇<E58AA7>█杈撳叆         鈹? 鈹?
鈹? 鈹?鈥?鍙<><E98D99>妯″紡鍒囨崲       鈹? 鈹?鈥?棰勬搷浣滃崱鐗?          鈹? 鈹?
鈹? 鈹?鈥?閿佸畾閬<E795BE>僵           鈹? 鈹?鈥?娑堟伅鍘嗗彶             鈹? 鈹?
鈹? 鈹斺攢鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹? 鈹斺攢鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹? 鈹?
鈹斺攢鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹?
              鈫?REST API (JSON)
鈹屸攢鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹?
鈹?    Node.js鍚庣<E98D9A> (backend/src/modules/dc/tool-c/)        鈹?
鈹? 鈥?鏂囦欢涓婁紶锛堝<E9949B>鐢╯torage鏈嶅姟锛夆渽                         鈹?
鈹? 鈥?浼氳瘽绠悊锛堝瓨鏁版嵁搴擄紝涓嶇敤鍐呭瓨Map锛夆渽                   鈹?
鈹? 鈥?LLM闆嗘垚锛堝<E9949B>鐢↙LMFactory锛夆渽                           鈹?
鈹? 鈥?鏃ュ織璁板綍锛堝<E9949B>鐢╨ogger锛夆渽                              鈹?
鈹? 鈥?寮傛<E5AFAE>浠诲姟锛堝<E9949B>鐢╦obQueue锛夆渽                            鈹?
鈹斺攢鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹?
              鈫?HTTP锛堝<E9949B>闇€Python鎵ц<E98EB5>锛?
鈹屸攢鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹?
鈹?   Python寰<6E>湇鍔★紙鍙<E7B499>€夛紝鎵╁睍鏂囨。澶勭悊寮曟搸锛?               鈹?
鈹? 鈥?DataFrame绠悊锛堝瓨鏁版嵁搴擄紝涓嶇敤鍐呭瓨锛?                  鈹?
鈹? 鈥?exec()浠爜鎵ц<E98EB5>                                        鈹?
鈹? 鈥?AST闈欐€佸畨鍏ㄦ<E98D8F>鏌?                                      鈹?
鈹? 鈥?JSON搴忓垪鍖栬繑鍥?                                       鈹?
鈹斺攢鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹€鈹?

鈿狅笍 浜戝師鐢熸灦鏋勫己鍒惰<E98D92>姹傦細

  • 鉁?澶嶇敤storage鏈嶅姟锛歚import { storage } from '@/common/storage'`
  • 鉁?澶嶇敤logger鏈嶅姟锛歚import { logger } from '@/common/logging'`
  • 鉁?澶嶇敤cache鏈嶅姟锛歚import { cache } from '@/common/cache'`
  • 鉁?澶嶇敤LLMFactory锛歚import { LLMFactory } from '@/common/llm'`
  • 鉁?澶嶇敤prisma瀹炰緥锛歚import { prisma } from '@/config/database'`
  • 鉁?Session瀛樻暟鎹<EFBFBD>锛氫笉鐢ㄥ唴瀛楳ap锛堣繚鍙嶈<EFBFBD>鑼冿級
  • 鉂?绂佹<EFBFBD><EFBFBD>湴鏂囦欢瀛樺偍锛欵xcel鐩存帴浠庡唴瀛樿В鏋?
  • 鉂?绂佹<EFBFBD>鏂板缓Prisma瀹炰緥锛氫娇鐢ㄥ叏灞€瀹炰緥

*鍏抽敭鍐崇瓥锛?

  • 鉁?涓嶇敤Apache Arrow锛欽SON澶熷揩锛?00琛?鈮?20KB锛?
  • 鉁?Session瀛樻暟鎹<EFBFBD>锛氱<EFBFBD>鍚堜簯鍘熺敓瑙勮寖锛屾敮鎸佸<EFBFBD>瀹炰緥
  • 鉁?涓嶅仛鎾ら攢锛氳妭鐪佸紑鍙戞椂闂达紝鐢ㄦ埛閲嶆柊涓婁紶鍗冲彲
  • 鉁?**涓嶄繚鐣欐牱寮?*锛氱洿鎺ョ敓鎴愭柊Excel

2.2 鎶€鏈<E282AC>爤閫夊瀷锛堚渽 澶嶇敤鐜版湁鎶€鏈<E282AC>爤锛?

鍓嶇<EFBFBD>锛坒rontend-v2锛?

{
  "framework": "React 19 + TypeScript 5 (宸叉湁)",
  "table": "AG Grid Community (鍏嶈垂鐗?",
  "ui": "Ant Design 5 (宸叉湁)",
  "state": "React Query v5 (宸叉湁)",
  "http": "axios (宸叉湁)",
  "routing": "React Router DOM v6 (宸叉湁)"
}

Node.js鍚庣<E98D9A>锛坆ackend锛?

{
  "framework": "Fastify v4 (宸叉湁)",
  "llm": "鉁?澶嶇敤 LLMFactory (骞冲彴閫氱敤鑳藉姏灞?",
  "storage": "鉁?澶嶇敤 storage鏈嶅姟 (骞冲彴鍩虹<E98DA9>灞?",
  "logging": "鉁?澶嶇敤 logger鏈嶅姟 (骞冲彴鍩虹<E98DA9>灞?",
  "cache": "鉁?澶嶇敤 cache鏈嶅姟 (骞冲彴鍩虹<E98DA9>灞?",
  "database": "鉁?澶嶇敤 prisma鍏ㄥ眬瀹炰緥 (骞冲彴鍩虹<E98DA9>灞?",
  "session": "鉁?PostgreSQL (dc_tool_c_sessions琛?",
  "excel": "xlsx 搴擄紙鍐呭瓨瑙f瀽锛?,
  "validation": "Joi"
}

Python寰<EFBFBD>湇鍔★紙鈿狅笍 鏍稿績鍔熻兘锛屾墿灞曠幇鏈夋湇鍔★級猸愨瓙猸愨瓙猸?

鍐崇瓥锛氣渽 绯荤粺宸叉湁Python寰<EFBFBD>湇鍔★紙FastAPI锛夛紝闇€鎵╁睍浠爜鎵ц<EFBFBD>鍔熻兘

馃摝 鐜版湁Python鏈嶅姟锛堝凡瀹屾垚锛夛細

  • 鉁?extraction_service锛欶astAPI + PyMuPDF + Pandas + openpyxl
  • 鉁?<EFBFBD>锛?000锛堝凡杩愯<E69DA9>锛?
  • 鉁?鍔熻兘锛歅DF/Docx/Txt鏂囨。鎻愬彇銆佽<E98A86>瑷€妫€娴?
  • 鉁?闆嗘垚锛歂ode.js閫氳繃ExtractionClient璋冪敤
  • 鉁?渚濊禆锛歅andas銆乷penpyxl銆乧hardet銆乴angdetect锛堝凡瀹夎<EFBFBD>锛?

馃敡 宸ュ叿C闇€瑕佺殑鏂板姛鑳斤細

鍔熻兘 鐜版湁鏈嶅姟 闇€姹? 鏂规<EFBFBD>
Pandas浠爜鎵ц<EFBFBD> 鉂?涓嶆敮鎸? 鉁?鏍稿績 鏂板<EFBFBD>API绔<EFBFBD> /api/dc/execute
Excel涓婁紶 鉂?涓嶆敮鎸? 鉁?闇€瑕? 澶嶇敤MultiPart涓婁紶
DataFrame绠 鉂?涓嶆敮鎸? 鉁?浼氳瘽 鏂板<EFBFBD>Session绠
*AST浠爜妫€鏌? 鉂?涓嶆敮鎸? 鉁?蹇呴』 鏂板<EFBFBD>AST妯″潡
Excel瀵煎嚭 鉂?涓嶆敮鎸? 鉁?闇€瑕? 浣跨敤openpyxl锛堝凡瀹夎<EFBFBD>锛?

鈿狅笍 涓嶉渶瑕侀噸澶嶅紑鍙戯細

  • 鉂?涓嶉渶瑕佹柊寤篜ython椤圭洰
  • 鉂?涓嶉渶瑕侀噸鏂板畨瑁匬andas/openpyxl锛堝凡瀹夎<E780B9>锛?
  • 鉂?涓嶉渶瑕侀噸鏂伴厤缃瓼astAPI锛堝凡杩愯<E69DA9>锛?
  • 鉂?涓嶉渶瑕侀噸鏂板啓Node.js璋冪敤閫昏緫锛圗xtractionClient宸插瓨鍦<E793A8>

*鉁?MVP鎵╁睍鏂规<E98F82>锛?

# extraction_service/services/dc_executor.py锛堟柊澧烇級
import pandas as pd
import ast
from typing import Dict, Any

def validate_code(code: str) -> Dict[str, Any]:
    """AST闈欐€佹<E282AC>鏌ワ紙瀹夊叏楠岃瘉锛?""
    try:
        tree = ast.parse(code)
        # 绂佹<E7BB82>import os銆乻ys銆乻ubprocess绛?
        for node in ast.walk(tree):
            if isinstance(node, ast.Import):
                for alias in node.names:
                    if alias.name in ['os', 'sys', 'subprocess', 'socket']:
                        return {'valid': False, 'error': f'绂佹<E7BB82>瀵煎叆{alias.name}'}
        return {'valid': True}
    except Exception as e:
        return {'valid': False, 'error': str(e)}

def execute_pandas_code(data: list, code: str) -> Dict[str, Any]:
    """鎵ц<EFBFBD>Pandas浠爜锛堚瓙鏍稿績鍔熻兘锛?""
    try:
        # 1. 瀹夊叏妫€鏌?
        validation = validate_code(code)
        if not validation['valid']:
            return {'success': False, 'error': validation['error']}
        
        # 2. 鍔犺浇鏁版嵁
        df = pd.DataFrame(data)
        
        # 3. 鎵ц<E98EB5>爜锛堟敞鍏<E6959E>f鍜宲d锛?
        exec(code, {'df': df, 'pd': pd})
        
        # 4. 杩斿洖缁撴灉锛堝墠100琛岋級
        return {
            'success': True,
            'data': df.head(100).to_dict('records'),
            'totalRows': len(df),
            'totalCols': len(df.columns),
            'columns': df.columns.tolist()
        }
    except Exception as e:
        return {'success': False, 'error': str(e)}
# extraction_service/main.py锛堟墿灞曪級
from services.dc_executor import execute_pandas_code, validate_code

@app.post("/api/dc/execute")
async def execute_code(
    data: List[Dict],
    code: str
):
    """宸ュ叿C锛氭墽琛孭andas浠爜"""
    result = execute_pandas_code(data, code)
    return JSONResponse(result)

@app.post("/api/dc/validate")
async def validate_code_endpoint(code: str):
    """宸ュ叿C锛欰ST浠爜妫€鏌?""
    result = validate_code(code)
    return JSONResponse(result)

鉁?Node.js璋冪敤锛堝<E9949B>鐢‥xtractionClient妯″紡锛夛細

// backend/src/modules/dc/tool-c/services/PythonExecutorService.ts
import axios from 'axios';

const EXTRACTION_SERVICE_URL = process.env.EXTRACTION_SERVICE_URL || 'http://localhost:8000';

export class PythonExecutorService {
  async executeCode(data: any[], code: string) {
    const response = await axios.post(`${EXTRACTION_SERVICE_URL}/api/dc/execute`, {
      data,
      code
    });
    return response.data;
  }
}

2.3 鏁版嵁娴佽<E5A8B4>璁?

*浼氳瘽鐢熷懡鍛ㄦ湡锛?

# 1. 鐢ㄦ埛涓婁紶鏂囦欢
POST /api/tool-c/session/init
{
  file: File,
  userId: string
}

# Node.js: 杞<>彂鍒癙ython
# Python: 
#   - 璇诲彇Excel 鈫?DataFrame
#   - 瀛樺叆鍐呭瓨锛歴essions[sessionId] = df
#   - 杩斿洖锛歴essionId + 鏁版嵁姒傝<E5A792>

# 2. 鐢ㄦ埛鍙戦€丄I鎸囦护
POST /api/tool-c/ai/execute
{
  sessionId: string,
  prompt: string
}

# Node.js:
#   - 鏋勫缓System Prompt锛堝寘鍚<E5AF98>暟鎹<E69A9F>笂涓嬫枃锛?
#   - 璋冪敤LLM鐢熸垚浠
#   - 杞<>彂浠爜鍒癙ython

# Python:
#   - AST妫€鏌?
#   - exec(code)淇<>敼df
#   - 杩斿洖鍓?00琛孞SON

# 3. 鐢ㄦ埛瀵煎嚭
GET /api/tool-c/session/export/{sessionId}

# Python:
#   - df.to_excel(buffer)
#   - 杩斿洖浜岃繘鍒舵祦

涓夈€佸姛鑳戒紭鍏堢骇鐭╅樀

3.1 P0绾э細蹇呴』寮€鍙戯紙鏍稿績闂<E7B8BE>幆锛夆瓙猸愨瓙猸愨瓙

ID 鍔熻兘 鎻忚堪 楠岃瘉鐩<EFBFBD> 宸ユ椂 璐熻矗浜?
P0-001 鏂囦欢涓婁紶 鍓嶇<EFBFBD>Upload缁勪欢 + 10MB闄愬埗 鑳藉惁瑙瀽Excel 0.5澶? 鍓嶇<EFBFBD>
P0-002 Session鍒濆<EFBFBD>鍖? 鍚庣<EFBFBD>鎺ユ敹鏂囦欢锛孭ython鍔犺浇DataFrame <EFBFBD>枃鍒楀悕銆丟BK缂栫爜 1澶? 鍚庣<EFBFBD>
P0-003 琛ㄦ牸灞曠ず AG Grid灞曠ず100琛屾暟鎹? 鍒楃被鍨嬭瘑鍒<EFBFBD>€佺┖鍊奸珮浜? 1澶? 鍓嶇<EFBFBD>
P0-004 AI瀵硅瘽UI 鍙充晶渚ц竟鏍忥紝娑堟伅鍒楄〃 鑱婂ぉ浜や簰娴佺晠 0.5澶? 鍓嶇<EFBFBD>
P0-005 System Prompt鏋勫缓 鍖呭惈鏁版嵁涓婁笅鏂囩殑Prompt AI鑳界悊瑙暟鎹<EFBFBD>粨鏋? 1澶? 鍚庣<EFBFBD>
P0-006 AI浠爜鐢熸垚 璋冪敤DeepSeek-V3鐢熸垚Pandas浠 鎴愬姛鐜?80% 2澶? 鍚庣<EFBFBD>
P0-007 AST瀹夊叏妫€鏌? 鎷︽埅鍗遍櫓浠g爜 import os<EFBFBD>嫤鎴? 1澶? Python
P0-008 爜鎵ц<EFBFBD> exec()鍦ㄦ矙绠变腑杩愯<E69DA9> <EFBFBD>敼DataFrame鎴愬姛 1澶? Python
P0-009 棰勬搷浣滃崱鐗? 灞曠ず浠爜锛岀敤鎴风璁ゅ悗鎵ц<EFBFBD> 鐢ㄦ埛鑳界湅鎳備唬鐮佹剰鍥? 0.5澶? 鍓嶇<EFBFBD>
P0-010 琛ㄦ牸鍒锋柊 鎵ц<EFBFBD>鍚庤嚜鍔ㄦ媺鍙栨柊鏁版嵁 鍓嶇<EFBFBD>瀹炴椂鏇存柊 0.5澶? 鍓嶇<EFBFBD>
P0-011 UI閿佸畾鏈哄埗 AI澶勭悊鏃惰〃鏍煎彉鐏?閬<> 鐗╃悊绂佹<EFBFBD>骞跺彂鎿嶄綔 0.5澶? 鍓嶇<EFBFBD>
P0-012 瀵煎嚭Excel 涓嬭浇澶勭悊鍚庣殑鏂囦欢 鏂囦欢瀹屾暣鎬? 1澶? Python

*P0灏忚<EFBFBD>锛?1.5澶?

3.2 P1绾э細蹇呴』楠岃瘉锛屽彲绠€鍖栧疄鐜?猸愨瓙猸愨瓙

ID 鍔熻兘 MVP绠€鍖栨柟妗? 瀹屾暣鐗? 宸ユ椂
P1-001 浼氳瘽绠$悊 杩涚▼鍐呭瓨Map锛堝崟瀹炰緥锛? Redis鍒嗗竷寮? 0.5澶?
P1-002 蹇冭烦淇濇椿 鍥哄畾10鍒嗛挓杩囨湡锛屼笉缁<EFBFBD> 鍓嶇<EFBFBD>蹇冭烦缁<EFBFBD> 0.5澶?
P1-003 缂栫爜妫€娴? chardet鑷<EFBFBD>姩妫€娴?鍙嬪ソ鎶ラ敊 <EFBFBD>姩杞<EFBFBD> 1澶?
P1-004 AI鑷<EFBFBD>垜淇<EFBFBD><EFBFBD> 澶辫触鍚庨噸璇?娆? 澶氭<EFBFBD>閲嶈瘯+瀛︿範 1澶?
P1-005 <EFBFBD>嵎妯℃澘 3涓<EFBFBD>父鐢ㄦā鏉匡紙骞撮緞鍒嗙粍绛夛級 10+妯℃澘搴? 0.5澶?

*P1灏忚<EFBFBD>锛?.5澶?

3.3 P2绾э細寤跺悗鎴栦笉鍋?猸愨瓙

鍔熻兘 寤跺悗鍘熷洜 浣曟椂鍋?
鎵嬪姩缂栬緫鍗曞厓鏍? MVP涓撴敞AI P2闃舵<EFBFBD>
鎾ら攢/鍥炴粴 鑺傜渷鍐呭瓨 P2闃舵<EFBFBD>
Apache Arrow JSON澶熺敤 鎬ц兘涓嶈揪鏍囨椂
Redis鍒嗗竷寮? 鍗曞疄渚嬪<EFBFBD>鐢? <EFBFBD>悜鎵╁睍鏃?
鏍峰紡淇濈暀 澶嶆潅搴﹂珮 P3闃舵<EFBFBD>
鎿嶄綔瀹¤<EFBFBD> 闈炴牳蹇? P3闃舵<EFBFBD>
澶歋heet鏀<EFBFBD> 绠€鍖栭€昏緫 P3闃舵<EFBFBD>

鍥涖€?鍛ㄨ<E98D9B>缁嗗紑鍙戣<E98D99>鍒?

Week 1锛氬熀纭€鏋舵瀯鎼<E780AF>缓锛?澶╋級

Day 1锛氱幆澧冩惌寤?+ 浠g爜缁撴瀯锛堚殸锔?鍙傝€僼ool-b缁撴瀯 + Python鐜<6E><E9909C>锛?

*浠诲姟娓呭崟锛?

  • 鍒涘缓椤圭洰鐩<EFBFBD>綍缁撴瀯锛?*鍙傝€僼ool-b**锛?

    backend/src/modules/dc/tool-c/           鈫?涓荤洰褰?
    鈹溾攢鈹€ services/                             鈫?涓氬姟閫昏緫灞?
    鈹?  鈹溾攢鈹€ SessionService.ts                 鈫?Session绠悊锛堝瓨鏁版嵁搴擄級
    鈹?  鈹溾攢鈹€ AICodeService.ts                  鈫?AI浠爜鐢熸垚
    鈹?  鈹溾攢鈹€ PythonExecutorService.ts          鈫?猸?Python浠爜鎵ц<E98EB5>锛堟牳蹇冿級
    鈹?  鈹斺攢鈹€ DataProcessService.ts             鈫?鏁版嵁澶勭悊閫昏緫
    鈹溾攢鈹€ controllers/                          鈫?鎺у埗鍣ㄥ眰
    鈹?  鈹斺攢鈹€ ToolCController.ts                鈫?HTTP璇锋眰澶勭悊
    鈹溾攢鈹€ routes/                               鈫?璺<>敱灞?
    鈹?  鈹斺攢鈹€ index.ts                          鈫?璺<>敱瀹氫箟
    鈹斺攢鈹€ utils/                                鈫?宸ュ叿鍑芥暟
        鈹溾攢鈹€ codeValidator.ts                  鈫?AST浠爜妫€鏌?
        鈹斺攢鈹€ pythonScripts/                    鈫?猸?Python鎵ц<E98EB5>鑴氭湰
            鈹斺攢鈹€ executor.py                   鈫?Pandas浠爜鎵ц<E98EB5>鍣?
    
    frontend-v2/src/modules/dc/pages/tool-c/  鈫?鍓嶇<E98D93>锛堝凡瀛樺湪锛?
    
  • 猸?鎵╁睍鐜版湁Python鏈嶅姟锛堟牳蹇冨姛鑳斤級

    # 绯荤粺宸叉湁Python寰<6E>湇鍔★紙extraction_service锛夛紝鍙<E7B49D>渶鎵╁睍鍔熻兘
    cd extraction_service
    
    # 1. 鍒涘缓DC鎵ц<E98EB5>鍣ㄦā鍧?
    cat > services/dc_executor.py << 'EOF'
    import pandas as pd
    import ast
    from typing import Dict, Any, List
    
    def validate_code(code: str) -> Dict[str, Any]:
        """AST闈欐€佹<E282AC>鏌ワ紙瀹夊叏楠岃瘉锛?""
        try:
            tree = ast.parse(code)
            # 绂佹<E7BB82>鍗遍櫓瀵煎叆
            forbidden_modules = ['os', 'sys', 'subprocess', 'socket', 'shutil', 'requests']
            for node in ast.walk(tree):
                if isinstance(node, ast.Import):
                    for alias in node.names:
                        if alias.name in forbidden_modules:
                            return {'valid': False, 'error': f'绂佹<E7BB82>瀵煎叆{alias.name}妯″潡'}
                elif isinstance(node, ast.ImportFrom):
                    if node.module in forbidden_modules:
                        return {'valid': False, 'error': f'绂佹<E7BB82>瀵煎叆{node.module}妯″潡'}
            return {'valid': True}
        except Exception as e:
            return {'valid': False, 'error': f'浠爜璇<E7889C>硶閿欒<E996BF>: {str(e)}'}
    
    def execute_pandas_code(data: List[Dict], code: str) -> Dict[str, Any]:
        """鎵ц<E98EB5>Pandas浠爜锛堚瓙鏍稿績鍔熻兘锛?""
        try:
            # 1. 瀹夊叏妫€鏌?
            validation = validate_code(code)
            if not validation['valid']:
                return {'success': False, 'error': validation['error']}
    
            # 2. 鍔犺浇鏁版嵁鍒癉ataFrame
            df = pd.DataFrame(data)
    
            # 3. 鎵ц<E98EB5>爜锛堟敞鍏<E6959E>f鍜宲d锛岄殧绂荤幆澧冿級
            local_env = {'df': df, 'pd': pd}
            exec(code, {'__builtins__': {}}, local_env)
    
            # 4. 鑾峰彇鎵ц<E98EB5>鍚庣殑df
            df_result = local_env.get('df', df)
    
            # 5. 杩斿洖缁撴灉锛堝墠100琛岋紝閬垮厤鏁版嵁閲忚繃澶э級
            return {
                'success': True,
                'data': df_result.head(100).to_dict('records'),
                'totalRows': len(df_result),
                'totalCols': len(df_result.columns),
                'columns': df_result.columns.tolist()
            }
        except Exception as e:
            return {
                'success': False,
                'error': f'浠爜鎵ц<E98EB5>澶辫触: {str(e)}'
            }
    EOF
    
    # 2. 鎵╁睍main.py锛屾坊鍔燚C绔<43>
    # 鍦╩ain.py鏈<79>熬娣诲姞锛?
    cat >> main.py << 'EOF'
    
    # ==================== DC宸ュ叿C绔<43>偣 ====================
    from services.dc_executor import execute_pandas_code, validate_code
    from pydantic import BaseModel
    
    class ExecuteRequest(BaseModel):
        data: List[Dict]
        code: str
    
    class ValidateRequest(BaseModel):
        code: str
    
    @app.post("/api/dc/execute")
    async def dc_execute_code(request: ExecuteRequest):
        """宸ュ叿C锛氭墽琛孭andas浠爜"""
        logger.info(f"DC Execute: code length={len(request.code)}, data rows={len(request.data)}")
        result = execute_pandas_code(request.data, request.code)
        return JSONResponse(result)
    
    @app.post("/api/dc/validate")
    async def dc_validate_code(request: ValidateRequest):
        """宸ュ叿C锛欰ST浠爜妫€鏌?""
        logger.info(f"DC Validate: code length={len(request.code)}")
        result = validate_code(request.code)
        return JSONResponse(result)
    EOF
    
  • *Node.js璋冪敤Python鏈嶅姟锛圥ythonExecutorService锛?

    // backend/src/modules/dc/tool-c/services/PythonExecutorService.ts
    import axios from 'axios';
    import { logger } from '@/common/logging';
    
    const EXTRACTION_SERVICE_URL = process.env.EXTRACTION_SERVICE_URL || 'http://localhost:8000';
    
    export interface ExecuteResult {
      success: boolean;
      data?: any[];
      totalRows?: number;
      totalCols?: number;
      columns?: string[];
      error?: string;
    }
    
    export class PythonExecutorService {
      private baseUrl: string;
    
      constructor() {
        this.baseUrl = EXTRACTION_SERVICE_URL;
      }
    
      /**
       * 鎵ц<E98EB5>Pandas浠爜锛堚瓙 鏍稿績鍔熻兘锛?
       * 澶嶇敤鐜版湁Python寰<6E>湇鍔★紝娣诲姞鏂扮<E98F82>鐐?
       */
      async executeCode(data: any[], code: string): Promise<ExecuteResult> {
        try {
          logger.info('Calling Python executor', { 
            dataRows: data.length, 
            codeLength: code.length 
          });
    
          const response = await axios.post<ExecuteResult>(
            `${this.baseUrl}/api/dc/execute`,
            { data, code },
            { timeout: 30000 } // 30绉掕秴鏃?
          );
    
          logger.info('Python execution success', { 
            totalRows: response.data.totalRows 
          });
    
          return response.data;
        } catch (error) {
          logger.error('Python execution failed', { error });
    
          if (axios.isAxiosError(error) && error.response) {
            throw new Error(error.response.data.error || 'Python execution failed');
          }
    
          throw new Error('鏃犳硶杩炴帴鍒癙ython鎵ц<E98EB5>鏈嶅姟');
        }
      }
    
      /**
       * AST浠爜妫€鏌ワ紙鎵ц<E98EB5>鍓嶉獙璇侊級
       */
      async validateCode(code: string): Promise<{ valid: boolean; error?: string }> {
        try {
          const response = await axios.post(
            `${this.baseUrl}/api/dc/validate`,
            { code },
            { timeout: 5000 }
          );
    
          return response.data;
        } catch (error) {
          logger.error('Code validation failed', { error });
          throw new Error('浠g爜楠岃瘉澶辫触');
        }
      }
    }
    
    export const pythonExecutorService = new PythonExecutorService();
    
  • **寮哄埗妫€鏌?*锛氱淇濆<E6B787>鐢ㄥ钩鍙版湇鍔?

    // backend/src/modules/dc/tool-c/services/SessionService.ts
    
    // 鉁?蹇呴』瀵煎叆杩欎簺骞冲彴鏈嶅姟
    import { storage } from '@/common/storage';
    import { logger } from '@/common/logging';
    import { cache } from '@/common/cache';
    import { prisma } from '@/config/database';
    
    // 鉂?绂佹<E7BB82><EFBFBD>繁瀹炵幇
    // const sessions = new Map()  鈫?杩濆弽瑙勮寖锛?
    
  • 鏁版嵁搴揝chema璁捐<EFBFBD>锛坉c_schema锛?

    // prisma/schema.prisma锛堟坊鍔犲埌dc_schema锛?
    model DcToolCSession {
      id            String   @id @default(uuid())
      userId        String
      sessionId     String   @unique
      fileName      String
      dataSnapshot  Json     // 瀛樺偍100琛岄<E7909B>瑙堟暟鎹?
      totalRows     Int
      totalCols     Int
      columns       Json     // 鍒椾俊鎭?
      expiresAt     DateTime // 10鍒嗛挓杩囨湡
      createdAt     DateTime @default(now())
    
      @@schema("dc_schema")
      @@map("dc_tool_c_sessions")
    }
    

*楠屾敹鏍囧噯锛?

  • 鉁?鏂囦欢澶圭粨鏋勪笌tool-b涓€鑷?
  • 鉁?瀵煎叆浜嗘墍鏈夊繀椤荤殑骞冲彴鏈嶅姟
  • 鉁?娌℃湁鍐呭瓨Map銆佹病鏈夋湰鍦版枃浠跺瓨鍌?

璐熻矗浜猴細 鍚庣<E98D9A>寮€鍙?


Day 2锛歋ession绠悊 + 鏁版嵁鍔犺浇锛堚殸锔?瀛樻暟鎹<E69A9F>簱锛屼笉鐢ㄥ唴瀛橈級

*浠诲姟娓呭崟锛?

  • 瀹炵幇SessionService锛?*瀛樻暟鎹<E69A9F>簱锛岀<E9949B>鍚堜簯鍘熺敓瑙勮寖**锛?
    // backend/src/modules/dc/tool-c/services/SessionService.ts
    import { storage } from '@/common/storage';
    import { logger } from '@/common/logging';
    import { prisma } from '@/config/database';
    import * as xlsx from 'xlsx';
    import chardet from 'chardet';
    
    export class SessionService {
      /**
       * 鍒涘缓Session锛堚渽 瀛樻暟鎹<E69A9F>簱锛屼笉鐢ㄥ唴瀛楳ap锛?
       */
      async createSession(userId: string, fileBuffer: Buffer, fileName: string): Promise<string> {
        // 1. 妫€娴嬬紪鐮?
        const detected = chardet.detect(fileBuffer);
        if (detected.encoding.toLowerCase() !== 'utf-8') {
          throw new Error(`鏂囦欢缂栫爜涓?{detected.encoding}锛岃<E9949B><EFBFBD>崲涓篣TF-8`);
        }
    
        // 2. 鍐呭瓨瑙瀽Excel锛堚渽 浜戝師鐢燂細涓嶈惤鐩橈級
        const workbook = xlsx.read(fileBuffer, { type: 'buffer' });
        const sheet = workbook.Sheets[workbook.SheetNames[0]];
        const data = xlsx.utils.sheet_to_json(sheet);
    
        // 3. 鎻愬彇鍒椾俊鎭?
        const columns = Object.keys(data[0] || {}).map(col => ({
          name: col,
          type: typeof data[0][col]
        }));
    
        // 4. Session瀛樻暟鎹<E69A9F>簱锛堚渽 绗﹀悎浜戝師鐢熻<E990A2>鑼冿級
        const sessionId = `session_${Date.now()}_${Math.random().toString(36)}`;
        await prisma.dcToolCSession.create({
          data: {
            sessionId,
            userId,
            fileName,
            dataSnapshot: data.slice(0, 100),  // 鍙<>瓨鍓?00琛岄<E7909B>瑙?
            totalRows: data.length,
            totalCols: columns.length,
            columns,
            expiresAt: new Date(Date.now() + 10 * 60 * 1000)  // 10鍒嗛挓杩囨湡
          }
        });
    
        // 5. 瀹屾暣鏁版嵁涓婁紶鍒癘SS锛堚渽 浜戝師鐢燂細鎸佷箙鍖栧瓨鍌<E793A8>    const dataKey = `dc/tool-c/${sessionId}/full-data.json`;
        await storage.uploadBuffer(dataKey, Buffer.from(JSON.stringify(data)));
    
        logger.info('Session created', { sessionId, totalRows: data.length });
    
        return sessionId;
      }
    
      /**
       * 鑾峰彇Session锛堜粠鏁版嵁搴撹<E690B4>鍙栵級
       */
      async getSession(sessionId: string) {
        const session = await prisma.dcToolCSession.findUnique({
          where: { sessionId }
        });
    
        if (!session || new Date() > session.expiresAt) {
          throw new Error('Session宸茶繃鏈?);
        }
    
        return session;
      }
    }
    

*娴嬭瘯鐢ㄤ緥锛?

  • 涓婁紶UTF-8缂栫爜鐨凟xcel锛屾<E9949B>甯歌В鏋?
  • 涓婁紶GBK缂栫爜鐨凟xcel锛岃<EFBFBD>鎷︽埅骞舵彁绀?
  • 涓婁紶涓<EFBFBD>枃鍒楀悕鐨凟xcel锛屾棤涔辩爜
  • Session瀛樺叆鏁版嵁搴擄紝鍙<EFBFBD>煡璇?
  • 10鍒嗛挓鍚嶴ession鑷<EFBFBD>姩杩囨湡

*楠屾敹鏍囧噯锛?

  • 鉁?Session瀛樺偍鍦ㄦ暟鎹<E69A9F>簱锛堜笉鏄<E7AC89>唴瀛楳ap锛?
  • 鉁?瀹屾暣鏁版嵁瀛樺偍鍦SS
  • 鉁?绗﹀悎浜戝師鐢熷紑鍙戣<E98D99>鑼?

璐熻矗浜猴細 Node.js鍚庣<E98D9A>


Day 3锛歂ode.js BFF + 鏂囦欢涓婁紶

*浠诲姟娓呭崟锛?

  • 鍒涘缓Fastify璺<EFBFBD>
    // backend/src/modules/dc/tool-c/routes/index.ts
    import { FastifyInstance } from 'fastify';
    
    export async function registerToolCRoutes(fastify: FastifyInstance) {
      // 鏂囦欢涓婁紶
      fastify.post('/api/v1/dc/tool-c/session/init', async (req, reply) => {
        const file = await req.file();
    
        // 1. 鏂囦欢澶у皬妫€鏌?
        if (file.file.bytesRead > 10 * 1024 * 1024) {
          return reply.code(413).send({
            success: false,
            error: '鏂囦欢杩囧ぇ锛岃<E9949B>鍘嬬缉鍚庨噸璇曪紙闄?0MB锛?
          });
        }
    
        // 2. 杞<>彂鍒癙ython鏈嶅姟
        const formData = new FormData();
        formData.append('file', file.file, file.filename);
    
        const response = await axios.post('http://localhost:8001/api/python/init', formData);
    
        return {
          success: true,
          sessionId: response.data.sessionId,
          data: response.data
        };
      });
    }
    
  • 闆嗘垚鍒颁富搴旂敤
    // backend/src/modules/dc/index.ts
    import { registerToolCRoutes } from './tool-c/routes';
    
    export async function registerDCRoutes(fastify: FastifyInstance) {
      await registerToolBRoutes(fastify);
      await registerToolCRoutes(fastify);  // 鏂板<E98F82>
    }
    

*娴嬭瘯鐢ㄤ緥锛?

  • 涓婁紶9MB鏂囦欢锛屾垚鍔?
  • 涓婁紶11MB鏂囦欢锛岃<EFBFBD>鎷︽埅
  • 骞跺彂涓婁紶2涓<EFBFBD>枃浠讹紝sessionId涓嶅啿绐?

*楠屾敹鏍囧噯锛?

  • 鉁?Node.js鑳芥<E991B3><EFBFBD>浆鍙戞枃浠跺埌Python
  • 鉁?鏂囦欢澶у皬闄愬埗鐢熸晥

璐熻矗浜猴細 Node.js鍚庣<E98D9A>


Day 4锛氬墠绔<E5A2A0><E7BB94>鏋舵惌寤?

*浠诲姟娓呭崟锛?

  • 鍒涘缓Tool C椤甸潰
    // frontend-v2/src/modules/dc/pages/tool-c/index.tsx
    import { AgGridReact } from 'ag-grid-react';
    import { Upload, Spin } from 'antd';
    
    export default function ToolCEditor() {
      const [sessionId, setSessionId] = useState<string>();
      const [data, setData] = useState<any[]>([]);
      const [columns, setColumns] = useState<any[]>([]);
      const [isLoading, setIsLoading] = useState(false);
    
      const handleUpload = async (file: File) => {
        setIsLoading(true);
        const formData = new FormData();
        formData.append('file', file);
    
        const response = await api.post('/api/v1/dc/tool-c/session/init', formData);
    
        setSessionId(response.data.sessionId);
        setData(response.data.data.preview);
        setColumns(response.data.data.columns);
        setIsLoading(false);
      };
    
      return (
        <div className="h-screen flex">
          {/* 宸︿晶锛氳〃鏍煎尯鍩?*/}
          <div className="flex-1">
            {!sessionId ? (
              <Upload beforeUpload={handleUpload}>
                <Button>涓婁紶Excel鏂囦欢锛堥檺10MB锛?/Button>
              </Upload>
            ) : (
              <AgGridReact
                rowData={data}
                columnDefs={columns.map(col => ({
                  field: col.name,
                  headerName: col.name
                }))}
              />
            )}
          </div>
    
          {/* 鍙充晶锛欰I渚ц竟鏍忥紙鍗犱綅锛?*/}
          <div className="w-96 border-l bg-white">
            <h3>AI鍔╂墜</h3>
          </div>
        </div>
      );
    }
    
  • 闆嗘垚AG Grid
    cd frontend-v2
    npm install ag-grid-react ag-grid-community
    
  • <EFBFBD>敱閰嶇疆
    // frontend-v2/src/modules/dc/routes.tsx
    {
      path: 'tool-c',
      element: <ToolCEditor />
    }
    

*娴嬭瘯鐢ㄤ緥锛?

  • 涓婁紶鏂囦欢锛岃〃鏍兼<EFBFBD><EFBFBD>樉绀?
  • <EFBFBD>枃鍒楀悕鏄剧ず姝
  • 绌哄€煎崟鍏冩牸鏈夎<EFBFBD>瑙夋彁绀?

*楠屾敹鏍囧噯锛?

  • 鉁?鐢ㄦ埛鑳界湅鍒板乏鍙冲垎鏍忕晫闈?
  • 鉁?琛ㄦ牸鑳藉睍绀?00琛屾暟鎹?

璐熻矗浜猴細 鍓嶇<E98D93>寮€鍙?


Day 5锛歋ystem Prompt鏋勫缓

*浠诲姟娓呭崟锛?

  • 鍒涘缓Prompt妯℃澘
    // backend/src/modules/dc/tool-c/prompts/system-prompt.ts
    export function buildSystemPrompt(dataContext: DataContext): string {
      return `# AI鍖荤枟鏁版嵁娓呮礂鍔╂墜 - 绯荤粺瑙掕壊
    
    

褰撳墠鏁版嵁缁撴瀯

  • 鎬昏<EFBFBD>鏁帮細${dataContext.totalRows} 琛?
  • 鎬诲垪鏁帮細${dataContext.totalCols} 鍒?
  • 鍒楀悕锛?{dataContext.columns.map(c => c.name).join(', ')}

鍓?琛屾暟鎹<E69A9F>ず渚?

${JSON.stringify(dataContext.headData, null, 2)}

涓ユ牸瑙勫垯

  1. <EFBFBD>兘浣跨敤pandas鎿嶄綔锛堝凡棰勫<EFBFBD>鍏ヤ负pd锛?
  2. 鍙橀噺鍚嶅繀椤绘槸df锛堜笉瑕佺敤鍏朵粬鍚嶅瓧锛?
  3. 灏卞湴淇<EFBFBD>敼锛歞f['new'] = ... 鎴?df.drop(...)
  4. 涓嶈<EFBFBD>print()銆乨isplay()绛夎緭鍑?
  5. 绂佹<EFBFBD>import os銆乻ys銆乺equests绛?

Few-shot绀轰緥锛堝垎灞傞毦搴︼細鍩虹<E98DA9>鈫掍腑绛夆啋楂樼骇锛?

馃煝 鍩虹<E98DA9>鍦烘櫙锛堝崟姝ラ<E5A79D>鎿嶄綔锛?

鍦烘櫙1锛氬勾榫勫垎缁?

鐢ㄦ埛锛?鎶婂勾榫勫ぇ浜?0鐨勬爣璁颁负鑰佸勾缁? 浠g爜锛? df['age_group'] = df['age'].apply(lambda x: '鑰佸勾缁? if pd.notna(x) and x > 60 else '闈炶€佸勾缁?)

鍦烘櫙2锛氬垹闄ょ己澶?

鐢ㄦ埛锛?鍒犻櫎娌℃湁鎮€匢D鐨勮<E990A8>" 浠g爜锛? df.dropna(subset=['patient_id'], inplace=True)

鍦烘櫙3锛氭€у埆缂栫爜

鐢ㄦ埛锛?鎶婃€у埆杞<E59F86>负鏁板瓧" 浠g爜锛? df['gender_code'] = df['gender'].map({'鐢?: 1, '濂?: 0})

馃煛 涓<>瓑鍦烘櫙锛堝<E9949B>姝ラ<E5A79D>鎴栬法鍒楅€昏緫锛?

鍦烘櫙4锛氳<EFBFBD>绠桸LR骞跺垎缁?

鐢ㄦ埛锛?璁畻涓<E795BB>х矑缁嗚優娣嬪反缁嗚優姣斿€糔LR锛屽苟鎸?.5鍒嗕负楂樹綆涓ょ粍" 浠g爜锛? df['NLR'] = df.apply(lambda row: row['neutrophil'] / row['lymphocyte'] if pd.notna(row['neutrophil']) and pd.notna(row['lymphocyte']) and row['lymphocyte'] > 0 else None, axis=1) df['NLR_group'] = df['NLR'].apply(lambda x: 'High' if pd.notna(x) and x > 2.5 else 'Low')

鍦烘櫙5锛氬瓧绗︿覆鎷嗗垎锛堣<EFBFBD>鍘嬶級

鐢ㄦ埛锛?鎶婅<E98EB6>鍘嬪垪鐨?120/80'鏍煎紡鎷嗗垎鎴愭敹缂╁帇鍜岃垝寮犲帇锛屽苟鍒ゆ柇鏄<E69F87>惁楂樿<E6A582>鍘? 浠g爜锛? df'systolic_bp', 'diastolic_bp' = df['blood_pressure'].str.split('/', expand=True) df['systolic_bp'] = pd.to_numeric(df['systolic_bp'], errors='coerce') df['diastolic_bp'] = pd.to_numeric(df['diastolic_bp'], errors='coerce') df['is_hypertension'] = ((df['systolic_bp'] > 140) | (df['diastolic_bp'] > 90)).astype(int)

鍦烘櫙6锛氭椂闂村樊璁畻锛堥€昏緫楠岃瘉锛?

鐢ㄦ埛锛?璁畻浣忛櫌澶╂暟锛屽<E9949B>鏋滃嚭闄㈡棩鏈熸棭浜庡叆闄㈡棩鏈熷垯鏍囪<E98F8D>涓哄紓甯? 浠g爜锛? df['admission_date'] = pd.to_datetime(df['admission_date'], errors='coerce') df['discharge_date'] = pd.to_datetime(df['discharge_date'], errors='coerce') df['hospital_days'] = (df['discharge_date'] - df['admission_date']).dt.days df['date_error'] = df['hospital_days'] < 0 df.loc[df['date_error'], 'hospital_days'] = None

馃敶 楂樼骇鍦烘櫙锛堝垎缁勮仛鍚堛€佹椂闂村簭鍒椼€佸尰瀛﹁<E7809B>鍒欙級

鍦烘櫙7锛氱敓瀛樻椂闂磋<EFBFBD>绠楋紙澶嶆潅鏉欢閫昏緫锛?

鐢ㄦ埛锛?鐢熸垚鐢熷瓨鐘舵€佸拰鐢熷瓨鏃堕棿锛屽<E9949B>鏋滄<E98F8B>浜℃棩鏈熷瓨鍦ㄥ垯鐘舵€佷负1锛屾椂闂翠负姝讳骸鏃ユ湡鍑忚瘖鏂<E79896>棩鏈燂紝鍚﹀垯鐘舵€佷负0锛屾椂闂翠负闅忚<E99785><EFBFBD><E98EB4>鏃ユ湡鍑忚瘖鏂<E79896>棩鏈? 浠g爜锛? df['diagnosis_date'] = pd.to_datetime(df['diagnosis_date'], errors='coerce') df['death_date'] = pd.to_datetime(df['death_date'], errors='coerce') df['followup_end_date'] = pd.to_datetime(df['followup_end_date'], errors='coerce') df['vital_status'] = df['death_date'].notna().astype(int) df['survival_days'] = df.apply(lambda row: (row['death_date'] - row['diagnosis_date']).days if pd.notna(row['death_date']) else (row['followup_end_date'] - row['diagnosis_date']).days, axis=1) df['survival_months'] = (df['survival_days'] / 30.44).round(1)

鍦烘櫙8锛氬垎缁勮仛鍚堬紙棣栨湯璁板綍锛?

鐢ㄦ埛锛?瀵规瘡涓<E798A1>偅鑰呮壘鍑虹<E98D91>涓€娆″寲鐤楁棩鏈熷拰鏈€鍚庝竴娆″寲鐤楁棩鏈燂紝璁畻鎸佺画鏃堕棿" 浠g爜锛? df['chemo_date'] = pd.to_datetime(df['chemo_date'], errors='coerce') patient_chemo = df.groupby('patient_id')['chemo_date'].agg(['min', 'max']).reset_index() patient_chemo.columns = ['patient_id', 'first_chemo', 'last_chemo'] patient_chemo['chemo_duration_days'] = (patient_chemo['last_chemo'] - patient_chemo['first_chemo']).dt.days df = df.merge(patient_chemo'patient_id', 'first_chemo', 'last_chemo', 'chemo_duration_days', on='patient_id', how='left')

鍦烘櫙9锛氭椂闂村簭鍒楀彉鍖栫巼

鐢ㄦ埛锛?鎸夋偅鑰匢D鍒嗙粍锛岃<E9949B>绠楁瘡娆¢殢璁跨浉姣斾笂娆殑鑲跨槫澶у皬鍙樺寲鐜? 浠g爜锛? df = df.sort_values(['patient_id', 'followup_date']) df['prev_tumor_size'] = df.groupby('patient_id')['tumor_size'].shift(1) df['tumor_change_rate'] = ((df['tumor_size'] - df['prev_tumor_size']) / df['prev_tumor_size'] * 100).round(2) df['tumor_change_rate'] = df['tumor_change_rate'].fillna(0)

鍦烘櫙10锛氬尰瀛﹁<EFBFBD>鍒欏紩鎿庯紙鑲濆姛鑳藉垎绾э級

鐢ㄦ埛锛?鏍规嵁ALT銆丄ST銆丄LP銆乀BIL鍒ゆ柇鑲濆姛鑳藉垎绾? 浠g爜锛? def classify_liver_function(row): abnormal_count = 0 if pd.notna(row.get('ALT')) and row['ALT'] > 40: abnormal_count += 1 if pd.notna(row.get('AST')) and row['AST'] > 40: abnormal_count += 1 if pd.notna(row.get('ALP')) and row['ALP'] > 125: abnormal_count += 1 if pd.notna(row.get('TBIL')) and row['TBIL'] > 20: abnormal_count += 1 if abnormal_count == 0: return '姝e父' elif abnormal_count == 1: return '杞诲害寮傚父' elif abnormal_count == 2: return '涓<>害寮傚父' else: return '閲嶅害寮傚父' df['liver_function_grade'] = df.apply(classify_liver_function, axis=1)

鐜板湪锛岃<EFBFBD>鍑嗗<EFBFBD>濂芥帴鏀剁敤鎴风殑鎸囦护銆傝<EFBFBD>浣忥細浠爜瑕佸畨鍏ㄣ€佸彲闈犮€佹槗鎳傦紝鑳藉<EFBFBD>鐞嗕粠鍩虹<EFBFBD>鍒伴珮绾х殑澶嶆潅鍖荤枟鍦烘櫙銆? `; }

- [ ] 闆嗘垚LLMFactory锛堚渽 澶嶇敤骞冲彴閫氱敤鑳藉姏灞傦級
```typescript
// backend/src/modules/dc/tool-c/services/AICodeService.ts
import { LLMFactory } from '@/common/llm';  // 鉁?澶嶇敤骞冲彴LLM鑳藉姏
import { logger } from '@/common/logging';  // 鉁?澶嶇敤鏃ュ織

export class AICodeService {
  /**
   * 鐢熸垚Pandas浠爜锛堚渽 澶嶇敤LLMFactory锛?
   */
  async generateCode(prompt: string, dataContext: DataContext): Promise<string> {
    logger.info('Generating Pandas code', { prompt, dataContext });
    
    // 鉁?澶嶇敤骞冲彴LLM鏈嶅姟
    const llm = LLMFactory.getLLM('deepseek-v3');
    
    const systemPrompt = buildSystemPrompt(dataContext);
    
    const response = await llm.chat([
      { role: 'system', content: systemPrompt },
      { role: 'user', content: prompt }
    ]);
    
    // 鎻愬彇绾<E5BD87>唬鐮侊紙鍘婚櫎Markdown鏍煎紡锛?
    const code = this.extractCode(response.content);
    
    logger.info('Code generated successfully', { codeLength: code.length });
    
    return code;
  }
  
  /**
   * AI鑷<49>垜淇<E59E9C><E6B787>锛堝け璐ュ悗閲嶈瘯1娆★級
   */
  async fixCode(originalCode: string, errorMsg: string, dataContext: DataContext): Promise<string> {
    logger.warn('Code execution failed, attempting self-repair', { errorMsg });
    
    const llm = LLMFactory.getLLM('deepseek-v3');
    
    const fixPrompt = `浠ヤ笅浠爜鎵ц<E98EB5>澶辫触锛岃<E9949B><EFBFBD><E6B787>锛?

閿欒<E996BF>淇℃伅锛?
${errorMsg}

鍘熷<E98D98>爜锛?
${originalCode}

鏁版嵁缁撴瀯锛?
${JSON.stringify(dataContext)}

璇风敓鎴愪慨澶嶅悗鐨勪唬鐮侊紙涓嶈<E6B693>鏈塎arkdown鏍煎紡锛夛細`;
    
    const response = await llm.chat([{ role: 'user', content: fixPrompt }]);
    
    return this.extractCode(response.content);
  }
  
  private extractCode(text: string): string {
    // 鍘婚櫎```python```鎴朻``鏍囪<E98F8D>
    const match = text.match(/```(?:python)?\n([\s\S]*?)\n```/);
    return match ? match[1] : text;
  }
}

*娴嬭瘯鐢ㄤ緥锛?

  • 杈撳叆"骞撮緞鍒嗙粍"锛岀敓鎴愭<E98EB4><EFBFBD>唬鐮?
  • 杈撳叆"鍒犻櫎绌鸿<E7BB8C>"锛岀敓鎴愭<E98EB4><EFBFBD>唬鐮?
  • 妫€鏌ヤ唬鐮佷腑鏄<EFBFBD>惁鍖呭惈鍗遍櫓璇<EFBFBD>

*楠屾敹鏍囧噯锛?

  • 鉁?AI鑳界敓鎴愬彲鎵ц<E98EB5>鐨凱andas浠
  • 鉁?浠爜绗﹀悎瑙勮寖锛堟棤print銆佹棤import锛?

璐熻矗浜猴細 Node.js鍚庣<E98D9A>


Week 2锛氭牳蹇冨姛鑳藉紑鍙戯紙5澶╋級

Day 6-7锛欰I浠爜鐢熸垚 + AST妫€鏌?

*Day 6浠诲姟锛?

  • 瀹炵幇AST闈欐€佹<EFBFBD>鏌?
    # python-service/code_validator.py
    import ast
    
    DANGEROUS_IMPORTS = {'os', 'sys', 'subprocess', 'requests', 'urllib'}
    DANGEROUS_BUILTINS = {'eval', 'exec', 'compile', 'open', '__import__'}
    
    def validate_code_safety(code: str) -> Tuple[bool, str]:
        try:
            tree = ast.parse(code)
    
            for node in ast.walk(tree):
                # 妫€鏌<E282AC>mport
                if isinstance(node, ast.Import):
                    for alias in node.names:
                        if alias.name in DANGEROUS_IMPORTS:
                            return False, f"绂佹<E7BB82>瀵煎叆锛歿alias.name}"
    
                # 妫€鏌ュ嚱鏁拌皟鐢?
                if isinstance(node, ast.Call):
                    if isinstance(node.func, ast.Name):
                        if node.func.id in DANGEROUS_BUILTINS:
                            return False, f"绂佹<E7BB82>浣跨敤锛歿node.func.id}"
    
            return True, "楠岃瘉閫氳繃"
        except SyntaxError as e:
            return False, f"璇<>硶閿欒<E996BF>锛歿str(e)}"
    

*Day 7浠诲姟锛?

  • 瀹炵幇AI浠爜鐢熸垚API
    // Node.js
    fastify.post('/api/v1/dc/tool-c/ai/generate', async (req, reply) => {
      const { sessionId, prompt } = req.body;
    
      // 1. 鑾峰彇鏁版嵁涓婁笅鏂?
      const context = await pythonService.getDataContext(sessionId);
    
      // 2. 璋冪敤AI鐢熸垚浠  const code = await aiService.generateCode(prompt, context);
    
      return {
        success: true,
        code,
        summary: `灏嗘墽琛屼互涓嬫搷浣滐細${extractSummary(code)}`
      };
    });
    

*娴嬭瘯鍦烘櫙锛?5涓<35>湡瀹炲尰鐤楁暟鎹<E69A9F>竻娲楀満鏅<E6BA80>級锛?

馃煝 鍩虹<E98DA9>鍦烘櫙锛?涓<>級- 鍗曟<E98D97>楠ゆ搷浣滐細

  1. "鎶婂勾榫勫ぇ浜?0鐨勬爣璁颁负鑰佸勾缁? - 绠€鍗曟潯浠跺垽鏂?
  2. "鍒犻櫎鎵€鏈夋偅鑰匢D涓虹┖鐨勮<E990A8>" - 鏁版嵁瀹屾暣鎬ф竻娲?
  3. "鎶婃€у埆杞<E59F86>负鏁板瓧锛岀敺1濂?" - 鍒嗙被鍙橀噺缂栫爜
  4. "璁畻BMI = 浣撻噸 / (韬<>珮/100)^2" - 绠€鍗曞叕寮忚<E5AFAE>绠?
  5. "鍒犻櫎缂哄け鐜囪秴杩?0%鐨勫垪" - 鍒楃骇鏁版嵁璐ㄩ噺鎺у埗

*馃煛 涓<>瓑鍦烘櫙锛?涓<>級- 澶氭<E6BEB6>楠ゆ垨璺ㄥ垪閫昏緫锛? 6. [ ] "鎶婅瘖鏂<E79896>棩鏈熷拰鍑洪櫌鏃ユ湡璁畻澶╂暟宸<E69A9F>紝濡傛灉鍑洪櫌鏃ユ湡鏃╀簬璇婃柇鏃ユ湡鍒欐爣璁颁负寮傚父" - 閫昏緫楠岃瘉 7. [ ] "鏍规嵁鐧界粏鑳炪€佷腑鎬х矑缁嗚優銆佹穻宸寸粏鑳炰笁涓<E7AC81>寚鏍囷紝璁畻NLR锛堜腑鎬х矑缁嗚優/娣嬪反缁嗚優锛夛紝骞舵寜2.5鍒嗕负楂樹綆涓ょ粍" - 澶氭<E6BEB6>楠よ<E6A5A0>绠? 8. [ ] "浠庣梾鐞嗘姤鍛婂垪涓<E59EAA>彁鍙朤NM鍒嗘湡锛岀敓鎴愭柊鍒楋紝濡傛灉娌℃湁鎻愬彇鍒板垯鏍囪<E98F8D>涓?鏈<>垎鏈?" - 鏂囨湰鎻愬彇锛堝彲鐢ㄦ<E990A2>鍒欙級 9. [ ] "鎶婅<E98EB6>鍘嬪垪涓<E59EAA>殑'120/80'鏍煎紡鎷嗗垎鎴愭敹缂╁帇鍜岃垝寮犲帇涓ゅ垪锛屽苟鍒ゆ柇鏄<E69F87>惁楂樿<E6A582>鍘嬶紙鏀剁缉鍘?140 or 鑸掑紶鍘?90锛? - 瀛楃<E7809B>涓插<E6B693>鐞?閫昏緫鍒ゆ柇 10. [ ] "鍒犻櫎閲嶅<E996B2>鐨勬偅鑰匢D锛屼繚鐣欐渶鏂扮殑涓€鏉¤<E98F89>褰曪紙鏍规嵁灏辫瘖鏃ユ湡锛? - 鍘婚噸+鎺掑簭

馃敶 楂樼骇鍦烘櫙锛?涓<>級- 澶嶆潅鍒嗙粍銆佹椂闂村簭鍒椼€佸尰瀛﹁<E7809B>鍒欙細 11. [ ] "瀵逛簬姣忎釜鎮€咃紝鎵惧嚭绗<E59AAD>竴娆″寲鐤楁棩鏈熷拰鏈€鍚庝竴娆″寲鐤楁棩鏈燂紝璁畻鍖栫枟鎸佺画鏃堕棿" - 鍒嗙粍鑱氬悎 12. [ ] "鐢熸垚鐢熷瓨鐘舵€佸彉閲忥細濡傛灉姝讳骸鏃ユ湡瀛樺湪鍒欎负1锛屽惁鍒欎负0锛涚敓鎴愮敓瀛樻椂闂达細濡傛灉姝讳骸鍒欎负锛堟<E9949B>浜℃棩鏈?璇婃柇鏃ユ湡锛夛紝鍚﹀垯涓猴紙闅忚<E99785><EFBFBD><E98EB4>鏃ユ湡-璇婃柇鏃ユ湡锛? - 澶嶆潅鏉′欢閫昏緫 13. [ ] "鏍规嵁澶氫釜瀹為獙瀹ゆ寚鏍囷紙ALT銆丄ST銆丄LP銆乀BIL锛夊垽鏂<E59EBD>倽鍔熻兘鍒嗙骇锛堟<E9949B>甯搞€佽交搴﹀紓甯搞€佷腑搴﹀紓甯搞€侀噸搴﹀紓甯革級" - 鍖诲<E98D96>瑙勫垯寮曟搸 14. [ ] "鎸夋偅鑰匢D鍒嗙粍锛屽<E9949B>姣忎釜鎮€呯殑澶氭<E6BEB6>闅忚<E99785>璁板綍锛岃<E9949B>绠楃浉閭讳袱娆箣闂寸殑鎸囨爣鍙樺寲鐜囷紙濡傝偪鐦ゅぇ灏忓彉鍖栫巼锛? - 鏃堕棿搴忓垪鍒嗘瀽 15. [ ] "鏍规嵁鍏ラ櫌鏃堕棿锛岃<E9949B>绠楁偅鑰呯殑瀛妭鍙橀噺锛堟槬澶忕<E6BEB6><EFBFBD>級锛岀劧鍚庣粺璁笉鍚屽<E98D9A>鑺傜殑鍙戠梾浜烘暟" - 鏃堕棿鐗瑰緛鎻愬彇+缁熻<E7BC81>鍒嗘瀽

*楠屾敹鏍囧噯锛堝垎灞傝<EFBFBD>姹傦級锛?

  • 鉁?**鍩虹<E98DA9>鍦烘櫙鎴愬姛鐜?> 90%**锛?/5鎴?/5鎴愬姛锛?
  • 鉁?**涓<>瓑鍦烘櫙鎴愬姛鐜?> 80%**锛?/5鎴愬姛锛?
  • 鉁?**楂樼骇鍦烘櫙鎴愬姛鐜?> 60%**锛?/5鎴愬姛锛?
  • 鉁?**鎬讳綋鎴愬姛鐜?> 80%**锛?2/15鍦烘櫙鎴愬姛锛?
  • 鉁?AST鑳芥嫤鎴猔import os`绛夊嵄闄╀唬鐮?
  • 鉂?濡傛灉鎬讳綋鎴愬姛鐜?< 60%锛?/15澶辫触锛夛紝MVP澶辫触锛岄渶瑕丳ivot鍒版ā鏉垮簱妯″紡

璐熻矗浜猴細 Node.js鍚庣<E98D9A> + Python寮€鍙?


Day 8锛氫唬鐮佹墽琛?+ 琛ㄦ牸鍒锋柊

*浠诲姟娓呭崟锛?

  • 瀹炵幇浠爜鎵ц<EFBFBD>API
    # Python
    @app.post("/api/python/execute")
    async def execute_code(request: ExecuteRequest):
        # 1. 鑾峰彇Session
        df = session_manager.get(request.sessionId)
    
        # 2. AST妫€鏌?
        is_safe, error_msg = validate_code_safety(request.code)
        if not is_safe:
            return {"success": False, "error": error_msg}
    
        # 3. 鎵ц<E98EB5>
        try:
            exec(request.code, {'df': df, 'pd': pd, 'np': np})
    
            # 4. 杩斿洖棰勮<E6A3B0>鏁版嵁
            preview = df.head(100).to_dict('records')
    
            return {
                "success": True,
                "preview": preview,
                "stats": {
                    "totalRows": len(df),
                    "totalCols": len(df.columns)
                }
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc()
            }
    
  • 鍓嶇<EFBFBD>鎵ц<EFBFBD>娴佺▼
    async function executeAICode(code: string) {
      // 1. 灞曠ず棰勬搷浣滃崱鐗?
      const confirmed = await showActionCard(code);
      if (!confirmed) return;
    
      // 2. 閿佸畾琛ㄦ牸
      setIsLocked(true);
    
      try {
        // 3. 鎵ц<E98EB5>    const response = await api.post('/api/v1/dc/tool-c/ai/execute', {
          sessionId,
          code
        });
    
        if (response.data.success) {
          // 4. 鍒锋柊琛ㄦ牸
          setData(response.data.preview);
          message.success('鎵ц<E98EB5>鎴愬姛锛?);
        } else {
          message.error(`鎵ц<E98EB5>澶辫触锛?{response.data.error}`);
        }
      } finally {
        // 5. 瑙i攣琛ㄦ牸
        setIsLocked(false);
      }
    }
    

*娴嬭瘯鐢ㄤ緥锛?

  • 鎵ц<EFBFBD>鎴愬姛锛岃〃鏍兼<EFBFBD><EFBFBD>埛鏂?
  • 鎵ц<EFBFBD>澶辫触锛屾樉绀洪敊璇<EFBFBD>俊鎭?
  • 鎵ц<EFBFBD>鏈熼棿锛岃〃鏍煎<EFBFBD>浜庨攣瀹氱姸鎬?

*楠屾敹鏍囧噯锛?

  • 鉁?浠爜鑳芥<E991B3><EFBFBD>慨鏀笵ataFrame
  • 鉁?鍓嶇<E98D93>鑳藉疄鏃剁湅鍒板彉鍖?

璐熻矗浜猴細 Python寮€鍙?+ 鍓嶇<E98D93>


Day 9锛歎I閿佸畾 + 棰勬搷浣滃崱鐗?

*浠诲姟娓呭崟锛?

  • 瀹炵幇AI瀵硅瘽UI
    function AIChatPanel({ sessionId }: Props) {
      const [messages, setMessages] = useState<Message[]>([]);
      const [input, setInput] = useState('');
      const [isProcessing, setIsProcessing] = useState(false);
    
      const handleSend = async () => {
        if (!input.trim()) return;
    
        // 1. 娣诲姞鐢ㄦ埛娑堟伅
        setMessages(prev => [...prev, {
          role: 'user',
          content: input
        }]);
    
        setIsProcessing(true);
    
        // 2. 璋冪敤AI鐢熸垚浠    const response = await api.post('/api/v1/dc/tool-c/ai/generate', {
          sessionId,
          prompt: input
        });
    
        // 3. 娣诲姞AI娑堟伅锛堝寘鍚<E5AF98>唬鐮侊級
        setMessages(prev => [...prev, {
          role: 'assistant',
          content: response.data.summary,
          code: response.data.code
        }]);
    
        setIsProcessing(false);
        setInput('');
      };
    
      return (
        <div className="flex flex-col h-full">
          {/* 娑堟伅鍒楄〃 */}
          <div className="flex-1 overflow-y-auto p-4">
            {messages.map((msg, idx) => (
              <MessageBubble key={idx} message={msg} />
            ))}
          </div>
    
          {/* 杈撳叆妗?*/}
          <div className="p-4 border-t">
            <Input.TextArea
              value={input}
              onChange={e => setInput(e.target.value)}
              placeholder="杈撳叆鎸囦护锛屼緥濡傦細鎶婂勾榫勫ぇ浜?0鐨勬爣璁颁负鑰佸勾缁?
              disabled={isProcessing}
            />
            <Button onClick={handleSend} disabled={isProcessing}>
              鍙戦€?
            </Button>
          </div>
        </div>
      );
    }
    
  • 瀹炵幇棰勬搷浣滃崱鐗?
    function ActionCard({ code, onConfirm, onCancel }: Props) {
      return (
        <Card className="mt-2 bg-slate-900 text-white">
          <div className="mb-2 text-xs text-slate-400">
            AI鐢熸垚鐨勪唬鐮?- 璇风璁ゅ悗鎵ц<EFBFBD>
          </div>
          <pre className="text-sm font-mono text-blue-300">
            {code}
          </pre>
          <div className="mt-3 flex gap-2">
            <Button type="primary" onClick={onConfirm}>
              杩愯<EFBFBD>
            </Button>
            <Button onClick={onCancel}>
              鍙栨秷
            </Button>
          </div>
        </Card>
      );
    }
    
  • 瀹炵幇UI閿佸畾
    <AgGridReact
      rowData={data}
      suppressClickEdit={isLocked}
      readOnlyEdit={isLocked}
    />
    
    {isLocked && (
      <div className="absolute inset-0 bg-black/20 flex items-center justify-center">
        <Spin tip="AI姝湪澶勭悊涓<E6828A>紝璇风◢鍊?.." />
      </div>
    )}
    

*楠屾敹鏍囧噯锛?

  • 鉁?鐢ㄦ埛鑳藉彂閫佹秷鎭?
  • 鉁?AI杩斿洖浠爜鏃跺睍绀洪<E7BB80>鎿嶄綔鍗
  • 鉁?鎵ц<E98EB5>鏈熼棿琛ㄦ牸閿佸畾

璐熻矗浜猴細 鍓嶇<E98D93>


Day 10锛氬<E9949B>鍑?+ 绔<>埌绔<E59F8C>祴璇?

*浠诲姟娓呭崟锛?

  • 瀹炵幇瀵煎嚭API
    @app.get("/api/python/export/{session_id}")
    async def export_excel(session_id: str):
        df = session_manager.get(session_id)
    
        # 鐢熸垚Excel
        output = io.BytesIO()
        df.to_excel(output, index=False, engine='openpyxl')
        output.seek(0)
    
        return StreamingResponse(
            output,
            media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            headers={
                'Content-Disposition': f'attachment; filename=cleaned_data_{session_id}.xlsx'
            }
        )
    
  • 鍓嶇<EFBFBD>瀵煎嚭鎸夐挳
    const handleExport = async () => {
      const response = await api.get(`/api/v1/dc/tool-c/session/export/${sessionId}`, {
        responseType: 'blob'
      });
    
      const url = window.URL.createObjectURL(response.data);
      const a = document.createElement('a');
      a.href = url;
      a.download = 'cleaned_data.xlsx';
      a.click();
    };
    
  • *<EFBFBD>埌绔<EFBFBD>祴璇曪紙瀹屾暣娴佺▼锛?
    1. 涓婁紶 test_data.xlsx (5000琛?脳 20鍒?
    2. AI鎸囦护锛?鎶婂勾榫勫ぇ浜?0鐨勬爣璁颁负鑰佸勾缁?
    3. 纭<><E7BAAD> 鈫?鎵ц<E98EB5> 鈫?琛ㄦ牸鍒锋柊锛堥獙璇佹柊澧炲垪锛?
    4. AI鎸囦护锛?鍒犻櫎鎮€匢D涓虹┖鐨勮<E990A8>"
    5. 纭<><E7BAAD> 鈫?鎵ц<E98EB5> 鈫?琛ㄦ牸鍒锋柊锛堥獙璇佽<E79287>鏁板噺灏戯級
    6. 鐐瑰嚮"瀵煎嚭" 鈫?涓嬭浇鏂囦欢
    7. 鎵撳紑涓嬭浇鐨勬枃浠讹紝楠岃瘉鏁版嵁姝g‘
    

*楠屾敹鏍囧噯锛?

  • 鉁?鏁翠釜娴佺▼ < 2鍒嗛挓
  • 鉁?瀵煎嚭鐨凟xcel鏁版嵁姝
  • 鉁?AI浠爜鎵ц<E98EB5>鎴愬姛

璐熻矗浜猴細 鍏ㄥ憳


Week 3锛氫紭鍖栦笌娴嬭瘯锛?澶╋級

Day 11-12锛氶敊璇<E6958A><E79287>鐞?+ AI鑷<49>垜淇<E59E9C><E6B787>

*浠诲姟娓呭崟锛?

  • 瀹炵幇AI鑷<EFBFBD>垜淇<EFBFBD><EFBFBD>
    async function executeWithRetry(code: string): Promise<ExecuteResult> {
      // 绗<>竴娆℃墽琛?
      let result = await pythonService.execute(sessionId, code);
    
      if (!result.success) {
        // 澶辫触锛岃<E9949B>AI淇<49><E6B787>
        const fixedCode = await aiService.fixCode(code, result.error);
    
        // 閲嶈瘯1娆?
        result = await pythonService.execute(sessionId, fixedCode);
    
        if (!result.success) {
          // 褰诲簳澶辫触
          return {
            success: false,
            error: '浠爜鎵ц<E98EB5>澶辫触锛岃<E9949B>灏濊瘯鏇磋<E98F87>缁嗗湴鎻忚堪鎮ㄧ殑闇€姹?,
            originalError: result.error
          };
        }
      }
    
      return result;
    }
    
  • 浼樺寲閿欒<EFBFBD>鎻愮ず
    function showErrorDetail(error: string) {
      const errorMap = {
        "KeyError: 'age'": "鍒楀悕'age'涓嶅瓨鍦<E793A8>紝璇锋<E79287>鏌ュ垪鍚嶆槸鍚︽<E98D9A>纭?,
        "ValueError": "鏁版嵁绫诲瀷涓嶅尮閰嶏紝璇锋<EFBFBD>鏌ユ暟鎹<EFBFBD>牸寮?,
        "MemoryError": "鏁版嵁閲忚繃澶э紝璇峰噺灏戞暟鎹<E69A9F><E98EB9>?
      };
    
      const friendlyMsg = errorMap[error] || error;
    
      Modal.error({
        title: '鎵ц<E98EB5>澶辫触',
        content: friendlyMsg
      });
    }
    

*娴嬭瘯鍦烘櫙锛堣竟鐣屾儏鍐碉級锛?

  • 鍒楀悕涓嶅瓨鍦<EFBFBD>df['nonexistent']
  • <EFBFBD>硶閿欒<EFBFBD>锛歚df[df['age'] > 60 and df['age'] < 80]`
  • 鏁版嵁绫诲瀷閿欒<EFBFBD>锛歚df['age'] + '瀛楃<E7809B>涓?`
  • 鍐呭瓨婧㈠嚭锛氬<EFBFBD>鐞嗚秴澶ф暟鎹?

*楠屾敹鏍囧噯锛?

  • 鉁?甯歌<E794AF>閿欒<E996BF>鑳借嚜鎴戜慨澶?
  • 鉁?鏃犳硶淇<E7A1B6><E6B787>鏃舵湁鍙嬪ソ鎻愮ず

璐熻矗浜猴細 Node.js鍚庣<E98D9A>


Day 13锛氬揩鎹锋ā鏉?+ 缂栫爜妫€娴?

*浠诲姟娓呭崟锛?

  • 瀹炵幇蹇<EFBFBD>嵎妯℃澘
    const QUICK_TEMPLATES = {
      '骞撮緞鍒嗙粍': {
        label: '骞撮緞鍒嗙粍锛?0宀佸垎鐣岋級',
        code: `df['age_group'] = pd.cut(df['age'], bins=[0,60,150], labels=['闈炶€佸勾','鑰佸勾'])`
      },
      '鍒犻櫎绌鸿<E7BB8C>': {
        label: '鍒犻櫎绌鸿<E7BB8C>',
        code: `df.dropna(how='all', inplace=True)`
      },
      '鎬у埆缂栫爜': {
        label: '鎬у埆缂栫爜锛堢敺1濂?锛?,
        code: `df['gender_code'] = df['gender'].map({'鐢?:1, '濂?:0})`
      }
    };
    
    function QuickActions() {
      return (
        <div className="p-4 border-t">
          <div className="text-xs text-slate-500 mb-2">蹇<>嵎鎿嶄綔</div>
          {Object.entries(QUICK_TEMPLATES).map(([key, template]) => (
            <Button
              key={key}
              size="small"
              onClick={() => executeTemplate(template.code)}
            >
              {template.label}
            </Button>
          ))}
        </div>
      );
    }
    
  • 瀹炵幇缂栫爜妫€娴?
    import chardet
    
    def detect_encoding(file_bytes: bytes) -> str:
        result = chardet.detect(file_bytes)
        encoding = result['encoding']
        confidence = result['confidence']
    
        if confidence < 0.8:
            raise ValueError(f"鏃犳硶纭<E7A1B6>畾鏂囦欢缂栫爜锛堢疆淇″害{confidence:.0%}锛?)
    
        return encoding
    
    @app.post("/api/python/init")
    async def init_session(file: UploadFile):
        content = await file.read()
    
        # 妫€娴嬬紪鐮?
        encoding = detect_encoding(content)
    
        if encoding.lower() not in ['utf-8', 'utf-8-sig']:
            return {
                "success": False,
                "error": f"鏂囦欢缂栫爜涓簕encoding}锛岃<EFBFBD><EFBFBD>崲涓篣TF-8鍚庨噸鏂颁笂浼?,
                "suggestion": "鍦‥xcel涓<6C>彟瀛樹负CSV UTF-8鏍煎紡"
            }
    
        # 姝e父鍔犺浇
        # ...
    

*楠屾敹鏍囧噯锛?

  • 鉁?蹇<>嵎妯℃澘涓€閿<E282AC>墽琛?
  • 鉁?GBK鏂囦欢琚<E6ACA2>弸濂芥嫤鎴?

璐熻矗浜猴細 鍓嶇<E98D93> + Python寮€鍙?


Day 14锛氭€ц兘娴嬭瘯 + 鍘嬪姏娴嬭瘯

*娴嬭瘯鍦烘櫙锛?

  • 鎬ц兘娴嬭瘯
    娴嬭瘯鏁版嵁锛?000琛?脳 20鍒楋紙绾?MB锛?
    
    鍦烘櫙1锛氫笂浼犳枃浠?
    - 鐩<>爣锛? 5绉?
    - 瀹炴祴锛歘___绉?
    
    鍦烘櫙2锛欰I鐢熸垚浠爜
    - 鐩<>爣锛? 5绉?
    - 瀹炴祴锛歘___绉?
    
    鍦烘櫙3锛氫唬鐮佹墽琛?鍒锋柊
    - 鐩<>爣锛? 3绉?
    - 瀹炴祴锛歘___绉?
    
    鍦烘櫙4锛氬<E9949B>鍑篍xcel
    - 鐩<>爣锛? 3绉?
    - 瀹炴祴锛歘___绉?
    
    鎬昏<E98EAC>锛? 16绉?
    
  • 鍘嬪姏娴嬭瘯
    鍦烘櫙1锛氬苟鍙戠敤鎴?
    - 5涓<35>敤鎴峰悓鏃朵笂浼犳枃浠?
    - 楠岃瘉锛歋ession闅旂<E99785>锛屼簰涓嶅奖鍝?
    
    鍦烘櫙2锛氬ぇ鏁版嵁閲?
    - 涓婁紶50000琛?脳 50鍒楋紙绾?0MB锛?
    - 楠岃瘉锛氫笉宕╂簝锛屽搷搴旀椂闂村彲鎺ュ彈
    
    鍦烘櫙3锛氳繛缁<E7B99B>搷浣?
    - 杩炵画鎵ц<E98EB5>10娆<30>I鎸囦护
    - 楠岃瘉锛氬唴瀛樹笉娉勬紡
    

鎬ц兘浼樺寲锛堝<EFBFBD>鏋滀笉杈炬爣锛夛細

  • 鍓嶇<EFBFBD>锛欰G Grid铏氭嫙婊氬姩閰嶇疆
  • 鍚庣<EFBFBD>锛欴ataFrame鎿嶄綔鏀逛负鎯版€ц<EFBFBD>绠?
  • Python锛氫娇鐢≒olars鏇夸唬Pandas锛堝<EFBFBD>鏋滈渶瑕侊級

*楠屾敹鏍囧噯锛?

  • 鉁?鍗曟<E98D97>鎿嶄綔 < 16绉?
  • 鉁?5涓<35>苟鍙戠敤鎴锋<E98EB4>甯稿伐浣?
  • 鉁?鏃犲唴瀛樻硠婕?

璐熻矗浜猴細 鍏ㄥ憳


Day 15锛氭枃妗?+ 婕旂ず鍑嗗<E98D91>

*浠诲姟娓呭崟锛?

  • 缂栧啓鐢ㄦ埛鏂囨。
    # 宸ュ叿C浣跨敤鎸囧崡
    
    ## 蹇<>€熷紑濮?
    1. 鐐瑰嚮"涓婁紶鏂囦欢"锛岄€夋嫨Excel锛堥檺10MB锛?
    2. 绛夊緟3-5绉掞紝琛ㄦ牸鍔犺浇瀹屾垚
    3. 鍦ㄥ彸渚<E5BDB8>I鍔╂墜杈撳叆鎸囦护锛屼緥濡傦細"鎶婂勾榫勫ぇ浜?0鐨勬爣璁颁负鑰佸勾缁?
    4. 鐐瑰嚮"杩愯<E69DA9>爜"纭<><E7BAAD>
    5. 鏌ョ湅琛ㄦ牸鑷<E789B8>姩鍒锋柊
    6. 瀹屾垚鎵€鏈夋搷浣滃悗锛岀偣鍑?瀵煎嚭"涓嬭浇缁撴灉
    
    ## 甯歌<E794AF><EFBFBD><E99782>
    Q: 鏂囦欢涓婁紶澶辫触锛屾彁绀烘枃浠惰繃澶э紵
    A: 璇峰皢Excel鏂囦欢鍘嬬缉鍒?0MB浠ュ唴锛屾垨鍒犻櫎涓嶉渶瑕佺殑鍒椼€?
    
    Q: 鍒楀悕鏄剧ず涔辩爜锛?
    A: 璇峰湪Excel涓<6C>彟瀛樹负"CSV UTF-8"鏍煎紡鍚庨噸鏂颁笂浼犮€?
    
  • 鍑嗗<EFBFBD>婕旂ず鏁版嵁
    鍒涘缓 demo_data.xlsx锛?
    - 100琛屾偅鑰呮暟鎹?
    - 鍖呭惈锛歱atient_id, name, age, gender, admission_date, bmi
    - 鏁呮剰鍒堕€犱竴浜涢棶棰橈細绌哄€笺€佸紓甯稿€笺€侀渶瑕佹竻娲楃殑鏁版嵁
    
  • 鍑嗗<EFBFBD>婕旂ず鑴氭湰
    婕旂ず娴佺▼锛?鍒嗛挓锛夛細
    1. 涓婁紶demo_data.xlsx
    2. AI鎸囦护锛?鎶婂勾榫勫ぇ浜?0鐨勬爣璁颁负鑰佸勾缁?
    3. AI鎸囦护锛?鍒犻櫎鎮€匢D涓虹┖鐨勮<E990A8>"
    4. AI鎸囦护锛?鎶婃€у埆杞<E59F86>负鏁板瓧锛岀敺1濂?"
    5. 瀵煎嚭缁撴灉
    6. 灞曠ず瀵煎嚭鐨凟xcel鏂囦欢
    

*楠屾敹鏍囧噯锛?

  • 鉁?鏂囨。娓呮櫚鏄撴噦
  • 鉁?婕旂ず娴佺晠鏃犲崱椤?
  • 鉁?婕旂ず鏁版嵁鑳戒綋鐜版牳蹇冨姛鑳?

璐熻矗浜猴細 鍏ㄥ憳


浜斻€侀<EFBFBD>闄╁簲瀵圭瓥鐣?

5.1 椋庨櫓娓呭崟涓庡簲瀵?

椋庨櫓 姒傜巼 褰卞搷 搴斿<EFBFBD>绛栫暐 闄嶇骇鏂规<EFBFBD>
*AI浠爜璐ㄩ噺浣庯紙鎴愬姛鐜?60%锛? 涓? 鑷村懡 1. 浼樺寲Prompt宸ョ▼
2. 澧炲姞Few-shot绀轰緥
3. 瀹炵幇鑷<E5B987>垜淇<E59E9C><E6B787>
Pivot锛氭敼鐢ㄤ唬鐮佹ā鏉垮簱
Apache Arrow闆嗘垚鍥伴毦 楂? 楂? 1. MVP涓嶇敤Arrow
2. 鐩存帴鐢↗SON
宸查檷绾э細MVP鐢↗SON
*Redis鍐呭瓨鎴愭湰楂? 涓? 涓? 1. MVP鐢ㄨ繘绋嬪唴瀛?br>2. 婵€杩涚殑Session杩囨湡 宸查檷绾э細鐢ap缂撳瓨
Python鍐呭瓨娉勬紡 涓? 楂? 1. 涓嶅仛鍘嗗彶蹇<E5BDB6>
2. 瀹氭湡閲嶅惎杩涚▼
SAE鑷<EFBFBD>姩閲嶅惎
<EFBFBD>枃Excel涔辩爜 楂? 涓? 1. chardet鑷<74>姩妫€娴?br>2. 鍙嬪ソ鎶ラ敊鎻愮ず 鏂囨。璇存槑杞琔TF-8
SAE鍐峰惎鍔ㄦ參 楂? 涓? 1. 鏈€灏忓疄渚嬫暟=1
2. 寮傛<E5AFAE>鍒濆<E98D92>鍖?
Loading浼樺寲
*鍓嶇<EFBFBD>AG Grid鎬ц兘宸? 浣? 涓? 1. 鍙<>睍绀?00琛?br>2. 铏氭嫙婊氬姩 *宸蹭紭鍖?

5.2 蹇<>€熷け璐ヨЕ鍙戝櫒

*绔嬪嵆鍋滄<EFBFBD>寮€鍙戠殑鏉欢锛?

  1. Day 7缁撴潫锛孉I浠爜鎴愬姛鐜?< 60%

    • 鍐崇瓥锛氭斁寮傾I Code Interpreter璺<72>
    • Pivot锛氭敼涓?浠g爜妯℃澘搴?+ 鍙傛暟鍖栭厤缃?
  2. *Day 10缁撴潫锛岀<E9949B>鍒扮<E98D92>鏃堕棿 > 30绉?

    • 鍐崇瓥锛氭€ц兘鏃犳硶鎺ュ彈
    • Pivot锛氭敼涓烘壒澶勭悊妯″紡锛堜笂浼?鈫?鍚庡彴澶勭悊 鈫?涓嬭浇锛?
  3. *Day 14缁撴潫锛?涓<>敤鎴锋祴璇曪紝閮芥棤娉曠嫭绔嬪畬鎴愪换鍔?

    • 鍐崇瓥锛氫氦浜掕<EFBFBD>璁″け璐?
    • Pivot锛氶噸鏂拌<EFBFBD><EFBFBD>I锛屽<EFBFBD>鍔犳柊鎵嬪紩瀵?

<EFBFBD>€侀獙鏀舵爣鍑?

6.1 鍔熻兘楠屾敹娓呭崟

缂栧彿 楠屾敹椤? 楠屾敹鏍囧噯 楠屾敹鏂瑰紡
F-001 鏂囦欢涓婁紶 鑳戒笂浼?0MB浠ュ唴鐨凟xcel 鎵嬪姩娴嬭瘯
F-002 缂栫爜妫€娴? GBK鏂囦欢琚<EFBFBD>弸濂芥嫤鎴? 鎵嬪姩娴嬭瘯
F-003 琛ㄦ牸灞曠ず 100琛屾暟鎹<EFBFBD><EFBFBD><EFBFBD>樉绀猴紝涓<EFBFBD>枃鏃犱贡鐮? 鎵嬪姩娴嬭瘯
F-004 AI瀵硅瘽 鑳藉彂閫佹秷鎭<EFBFBD>紝鎺ユ敹鍥炲<EFBFBD> 鎵嬪姩娴嬭瘯
F-005 浠g爜鐢熸垚 *10涓<EFBFBD>満鏅<EFBFBD>紝8涓<EFBFBD>垚鍔燂紙80%锛? <EFBFBD>姩鍖栨祴璇?
F-006 AST妫€鏌? 鎷︽埅import os绛夊嵄闄╀唬鐮? 鍗曞厓娴嬭瘯
F-007 爜鎵ц<EFBFBD> 鑳芥<EFBFBD><EFBFBD>慨鏀笵ataFrame 闆嗘垚娴嬭瘯
F-008 琛ㄦ牸鍒锋柊 鎵ц<EFBFBD>鍚庤嚜鍔ㄦ洿鏂? 鎵嬪姩娴嬭瘯
F-009 UI閿佸畾 AI澶勭悊鏃惰〃鏍煎彧璇?閬<> 鎵嬪姩娴嬭瘯
F-010 瀵煎嚭Excel 涓嬭浇鐨勬枃浠舵暟鎹<EFBFBD><EFBFBD>纭? 鎵嬪姩娴嬭瘯

6.2 鎬ц兘楠屾敹鏍囧噯

鎸囨爣 <EFBFBD>爣鍊? 楠屾敹鏂瑰紡
鏂囦欢涓婁紶鍒拌〃鏍兼樉绀? < 5绉? 鎬ц兘娴嬭瘯
AI鐢熸垚浠 < 5绉? 鎬ц兘娴嬭瘯
爜鎵ц<EFBFBD>+鍒锋柊 < 3绉? 鎬ц兘娴嬭瘯
瀵煎嚭Excel < 3绉? 鎬ц兘娴嬭瘯
*<EFBFBD>埌绔<EFBFBD>€绘椂闂? *< 16绉? 鎬ц兘娴嬭瘯
骞跺彂鐢ㄦ埛鏁? 鈮?5浜? 鍘嬪姏娴嬭瘯
鍐呭瓨鍗犵敤 < 2GB锛?鐢ㄦ埛锛? 鍘嬪姏娴嬭瘯

6.3 瀹夊叏楠屾敹鏍囧噯

鎸囨爣 楠屾敹鏍囧噯 楠屾敹鏂瑰紡
爜娌欑<EFBFBD> 鎷︽埅鎵€鏈夊嵄闄╀唬鐮? 娓楅€忔祴璇?
Session闅旂<EFBFBD> 鐢ㄦ埛A鐪嬩笉鍒扮敤鎴稡鏁版嵁 骞跺彂娴嬭瘯
Session杩囨湡 10鍒嗛挓鍚庤嚜鍔ㄦ竻鐞? 鏃堕棿娴嬭瘯

涓冦€佸揩閫熷け璐ユ満鍒?

7.1 鍏抽敭妫€鏌ョ偣

Checkpoint 1 (Day 5缁撴潫)锛?
鈹溾攢 System Prompt鑳藉惁璁〢I鐞嗚В鏁版嵁锛?
鈹溾攢 AI鑳界敓鎴怭andas浠爜鍚楋紵
鈹斺攢 鍐崇瓥锛氱户缁?or 璋冩暣Prompt绛栫暐

Checkpoint 2 (Day 7缁撴潫)锛?
鈹溾攢 AI浠爜鎴愬姛鐜?鈮?80%锛?
鈹溾攢 濡傛灉 < 60%锛氱珛鍗冲仠姝<E4BBA0>紝鏀圭敤妯℃澘搴?
鈹斺攢 濡傛灉 60-80%锛氱户缁<E688B7>紭鍖朠rompt

Checkpoint 3 (Day 10缁撴潫)锛?
鈹溾攢 绔<>埌绔<E59F8C>祦绋嬭兘璺戦€氾紵
鈹溾攢 鎬ц兘 < 16绉掞紵
鈹斺攢 鍐崇瓥锛氱户缁?or 鎬ц兘浼樺寲

Checkpoint 4 (Day 14缁撴潫)锛?
鈹溾攢 鐢ㄦ埛娴嬭瘯閫氳繃锛?
鈹溾攢 鏃犻噸澶<E599B8>ug锛?
鈹斺攢 鍐崇瓥锛氬彂甯?or 淇<><E6B787>Bug

7.2 Pivot鍐崇瓥鏍?

濡傛灉 AI浠爜鎴愬姛鐜?< 60%锛?
  鈹溾攢 Pivot 1锛氭敼鐢?浠g爜妯℃澘搴?+ 鍙傛暟鍖栭厤缃?
  鈹?  鈹斺攢 鐢ㄦ埛閫夋嫨妯℃澘 鈫?濉<>啓鍙傛暟 鈫?鐢熸垚浠g爜
  鈹?
  鈹溾攢 Pivot 2锛欰I鍙樻垚"杈呭姪寤鸿<E5AFA4>"瑙掕壊
  鈹?  鈹斺攢 鐢ㄦ埛鎵嬪姩鍐欎唬鐮侊紝AI鎻愪緵寤鸿<E5AFA4>
  鈹?
  鈹斺攢 Pivot 3锛氱畝鍖栦负"鎵瑰<E98EB5>鐞嗘ā寮?
      鈹斺攢 涓婁紶 鈫?閫夋嫨棰勮<E6A3B0>鎿嶄綔 鈫?鍚庡彴澶勭悊 鈫?涓嬭浇

濡傛灉 鎬ц兘鏃犳硶鎺ュ彈锛? 30绉掞級锛?
  鈹溾攢 鏂规<E98F82>1锛氬紩鍏<E7B4A9>pache Arrow
  鈹溾攢 鏂规<E98F82>2锛氫娇鐢≒olars鏇夸唬Pandas
  鈹斺攢 鏂规<E98F82>3锛氭敼涓烘壒澶勭悊+寮傛<E5AFAE>閫氱煡

濡傛灉 鐢ㄦ埛鏃犳硶鐙<E7A1B6>珛瀹屾垚浠诲姟锛?
  鈹溾攢 鏂规<E98F82>1锛氬<E9949B>鍔犱氦浜掑紡鏂版墜寮曞<E5AFAE>
  鈹溾攢 鏂规<E98F82>2锛氭彁渚涚ず渚嬫暟鎹<E69A9F>泦
  鈹斺攢 鏂规<E98F82>3锛氱畝鍖朥I锛屽噺灏戦€夐」

<EFBFBD>€侀檮褰?

8.1 娴嬭瘯鏁版嵁鍑嗗<E98D91>

鍒涘缓鏍囧噯娴嬭瘯鏁版嵁闆嗭細

# create_test_data.py
import pandas as pd
import numpy as np

# 鐢熸垚5000琛屾祴璇曟暟鎹?
data = {
    'patient_id': [f'P{i:04d}' for i in range(1, 5001)],
    'name': [f'鎮€厈i}' for i in range(1, 5001)],
    'age': np.random.randint(18, 90, 5000),
    'gender': np.random.choice(['鐢?, '?], 5000),
    'admission_date': pd.date_range('2023-01-01', periods=5000, freq='H'),
    'weight': np.random.uniform(45, 95, 5000).round(1),
    'height': np.random.uniform(150, 190, 5000).round(0),
    'diagnosis': np.random.choice(['鑲虹檶', '绯栧翱鐥?, '楂樿<EFBFBD>?], 5000)
}

df = pd.DataFrame(data)

# 鏁呮剰鍒堕€犻棶棰?
df.loc[np.random.choice(5000, 100, replace=False), 'age'] = None  # 100涓<30>己澶?
df.loc[np.random.choice(5000, 10, replace=False), 'age'] = 150   # 10涓<30>紓甯稿€?
df.loc[np.random.choice(5000, 50, replace=False), 'patient_id'] = None  # 50涓<30>┖ID

df.to_excel('test_data.xlsx', index=False)

8.2 10涓<30>吀鍨嬪満鏅<E6BA80>祴璇曠敤渚?

# test_ai_scenarios.py
test_cases = [
    {
        "id": "TC-001",
        "prompt": "鎶婂勾榫勫ぇ浜?0鐨勬偅鑰呮爣璁颁负鑰佸勾缁?,
        "expected_code": "df['age_group'] = df['age'].apply(lambda x: '鑰佸勾缁? if pd.notna(x) and x > 60 else '闈炶€佸勾缁?)",
        "verify": lambda df: 'age_group' in df.columns
    },
    {
        "id": "TC-002",
        "prompt": "鍒犻櫎鎵€鏈夋偅鑰匢D涓虹┖鐨勮<E990A8>",
        "expected_code": "df.dropna(subset=['patient_id'], inplace=True)",
        "verify": lambda df: df['patient_id'].isnull().sum() == 0
    },
    # ... 鍏朵綑8涓<38>満鏅?
]

8.3 鐜<><E9909C>閰嶇疆娓呭崟

*Node.js渚濊禆锛?

{
  "dependencies": {
    "fastify": "^4.0.0",
    "axios": "^1.6.0",
    "joi": "^17.11.0",
    "@fastify/multipart": "^8.0.0"
  }
}

*Python渚濊禆锛?

fastapi==0.115.0
uvicorn==0.30.0
pandas==2.2.0
openpyxl==3.1.0
chardet==5.2.0
python-multipart==0.0.9

涔濄€侀」鐩<EFBFBD><EFBFBD>鐞?

9.1 鍥㈤槦閰嶇疆

瑙掕壊 浜烘暟 鑱岃矗
鍓嶇<EFBFBD>寮€鍙? 1浜? React + AG Grid + UI
Node.js鍚庣<E98D9A> 1浜? BFF + LLM闆嗘垚 + Prompt宸ョ▼
Python寮€鍙? 1浜? FastAPI + DataFrame + AST妫€鏌?
鎬昏<EFBFBD> *3浜? 3鍛<EFBFBD>紙15澶╋級

9.2 娌熼€氭満鍒?

  • 姣忔棩绔欎細锛?5鍒嗛挓锛屽悓姝ヨ繘搴﹀拰闂<E68BB0><E99782>
  • 鍏抽敭妫€鏌ョ偣锛欴ay 5銆?銆?0銆?4
  • <EFBFBD><EFBFBD>鍗囩骇锛氶樆濉為棶棰?灏忔椂鍐呭崌绾?
  • 鏂囨。鏇存柊锛氭瘡鏃ユ洿鏂板紑鍙戣<EFBFBD>褰?

9.3 浠g爜绠$悊

*鍒嗘敮绛栫暐锛?

main (绋冲畾鐗?
  鈹斺攢鈹€ develop (寮€鍙戠増)
      鈹溾攢鈹€ feature/tool-c-frontend
      鈹溾攢鈹€ feature/tool-c-backend
      鈹斺攢鈹€ feature/tool-c-python

*鎻愪氦瑙勮寖锛?

feat: 鏂板<E98F82>AI浠爜鐢熸垚鍔熻兘
fix: 淇<><E6B787>琛ㄦ牸鍒锋柊Bug
test: 澧炲姞AST妫€鏌ユ祴璇曠敤渚?
docs: 鏇存柊寮€鍙戞枃妗?

鍗併€佹€荤粨

鏍稿績鎴愬姛瑕佺礌

  1. 鉁?AI浠爜璐ㄩ噺锛氭垚鍔熺巼 > 80%锛堟牳蹇冨亣璁撅級
  2. 鉁?**鎬ц兘鍙<E58598>帴鍙?*锛氱<E9949B>鍒扮<E98D92> < 16绉?
  3. 鉁?**浜や簰绠€鍗?*锛氱敤鎴锋棤闇€鏂囨。灏辫兘鐢?

椋庨櫓鎺у埗

  1. 鉁?**蹇<>€熷け璐?*锛?澶╅獙璇丄I鑳藉姏锛屼笉琛岀珛鍗砅ivot
  2. 鉁?**鍔″疄鎶€鏈?*锛欽SON涓嶇敤Arrow锛屽唴瀛樹笉鐢≧edis
  3. 鉁?**闄嶇骇鏂规<E98F82>**锛氬噯澶囧ソ妯℃澘搴撱€佹壒澶勭悊绛塒lan B

鏃堕棿鑺傜偣

  • Week 1锛氬熀纭€鏋舵瀯锛?澶╋級
  • Week 2锛氭牳蹇冨姛鑳斤紙5澶╋級
  • Week 3锛氫紭鍖栨祴璇曪紙5澶╋級
  • **鎬昏<E98EAC>**锛?5涓<35>伐浣滄棩

馃摑 鏂囨。淇<E38082><E6B787>璁板綍

V1.3锛?025-12-06锛? 鍙戠幇鐜版湁Python鏈嶅姟 猸?閲嶅ぇ鍙戠幇

**淇<><E6B787>鍐呭<E98D90>**锛氭<E9949B>鏌ョ郴缁熷彂鐜板凡鏈塒ython寰<6E>湇鍔★紝涓嶉渶瑕侀噸澶嶅紑鍙戯細

<EFBFBD><EFBFBD>1锛氬<EFBFBD>鐢ㄧ幇鏈塒ython鏈嶅姟锛屼笉閲嶅<EFBFBD>閫犺疆 猸愨瓙猸愨瓙猸?

  • 閲嶅ぇ鍙戠幇锛氱郴缁熷凡鏈?extraction_service/锛團astAPI + Pandas + openpyxl锛?
  • 鐜版湁鍔熻兘锛?
    • 鉁?PDF/Docx/Txt鏂囨。鎻愬彇锛圥yMuPDF + Mammoth锛?
    • 鉁?Pandas銆乷penpyxl銆乧hardet銆乴angdetect宸插畨瑁?
    • 鉁?FastAPI妗嗘灦宸茶繍琛岋紙绔<E7B499>彛8000锛?
    • 鉁?Node.js宸叉湁ExtractionClient闆嗘垚
  • **鏂板<E98F82>鏂规<E98F82>**锛?
    • 鉁?鎵╁睍鐜版湁鏈嶅姟锛屾坊鍔?/api/dc/execute<>
    • 鉁?鏂板<E98F82> dc_executor.py 妯″潡锛圓ST妫€鏌?+ 浠爜鎵ц<E98EB5>锛?
    • 鉁?澶嶇敤ExtractionClient妯″紡璋冪敤
  • **閬垮厤閲嶅<E996B2>**锛?
    • 鉂?涓嶉渶瑕佹柊寤篜ython椤圭洰
    • 鉂?涓嶉渶瑕侀噸鏂板畨瑁呬緷璧?
    • 鉂?涓嶉渶瑕侀噸鏂板啓HTTP璋冪敤閫昏緫

V1.2锛?025-12-06锛? Python鎵ц<E98EB5><EFBFBD><E9909C> + 澶嶆潅鍦烘櫙 鈿狅笍 鏍稿績鍔熻兘

**淇<><E6B787>鍐呭<E98D90>**锛氭牴鎹<E789B4>敤鎴峰弽棣堬紝鏄庣Python浠爜鎵ц<E98EB5><EFBFBD>牳蹇冨姛鑳斤細

<EFBFBD><EFBFBD>1锛歅ython鎵ц<EFBFBD><EFBFBD>牳蹇冿紝涓嶆槸鍙<EFBFBD>€?猸愨瓙猸愨瓙猸?

  • **鍘熼敊璇?*锛氳<E9949B>"MVP闃舵<E99783><EFBFBD>兘涓嶉渶瑕丳ython寰<6E>湇鍔?
  • **宸蹭慨姝?锛?Python浠爜鎵ц<EFBFBD><EFBFBD>伐鍏稢鐨勬牳蹇冧环鍊硷紝蹇呴』瀹炵幇
  • **鏂板<E98F82>鍐呭<E98D90>**锛?
    • Day 1澧炲姞Python鐜<6E><E9909C><EFBFBD>
    • 鏂板<EFBFBD>PythonExecutorService锛圢ode.js 鈫?Python閫氫俊锛?
    • 鏂板<EFBFBD>executor.py锛圥andas浠爜鎵ц<E98EB5><EFBFBD>
    • 鎶€鏈<EFBFBD>柟妗堬細Node.js child_process璋冪敤Python鑴氭湰

<EFBFBD><EFBFBD>2锛氭祴璇曞満鏅<EFBFBD>粠绠€鍗曞埌澶嶆潅 鉁?

  • **鍘熼棶棰?*锛?0涓<30>祴璇曞満鏅<E6BA80>繃浜庣畝鍗?
  • **宸蹭慨姝?*锛?5涓<35>湡瀹炲尰鐤楁暟鎹<E69A9F>竻娲楀満鏅?
    • 馃煝 鍩虹<E98DA9>鍦烘櫙5涓<35>細鍗曟<E98D97>楠ゆ搷浣?
    • 馃煛 涓<>瓑鍦烘櫙5涓<35>細澶氭<E6BEB6>楠ゃ€佽法鍒楅€昏緫
    • 馃敶 楂樼骇鍦烘櫙5涓<35>細鍒嗙粍鑱氬悎銆佹椂闂村簭鍒椼€佸尰瀛﹁<E7809B>鍒?
  • 鏂板<EFBFBD>鍦烘櫙锛?
    • 澶嶆潅鏉欢閫昏緫锛堢敓瀛樻椂闂磋<EFBFBD>绠楋級
    • 鍖诲<EFBFBD>瑙勫垯寮曟搸锛堣倽鍔熻兘鍒嗙骇锛?
    • 鏃堕棿搴忓垪鍒嗘瀽锛堟寚鏍囧彉鍖栫巼锛?
    • 鏂囨湰鎻愬彇锛圱NM鍒嗘湡锛?
    • 瀛楃<EFBFBD>涓插<EFBFBD>鐞嗭紙琛€鍘嬫媶鍒嗭級

<EFBFBD><EFBFBD>3锛氶獙鏀舵爣鍑嗗垎灞?鉁?

  • **鍘熸爣鍑?*锛氭€讳綋鎴愬姛鐜?> 80%
  • **鏂版爣鍑?*锛?
    • 鍩虹<EFBFBD>鍦烘櫙鎴愬姛鐜?> 90%
    • <EFBFBD>瓑鍦烘櫙鎴愬姛鐜?> 80%
    • 楂樼骇鍦烘櫙鎴愬姛鐜?> 60%
    • 鎬讳綋鎴愬姛鐜?> 80%锛?2/15鍦烘櫙锛?

<EFBFBD><EFBFBD>4锛氭牳蹇冨亣璁鹃獙璇?鉁?

  • 鏂板<EFBFBD>H2锛歅ython浠爜鎵ц<EFBFBD><EFBFBD><EFBFBD>绋冲畾鍙<EFBFBD>
  • <EFBFBD>敼H1锛氫粠"鐢熸垚浠g爜"鏀逛负"鐢熸垚浠g爜骞舵垚鍔熸墽琛?
  • 寮鸿皟锛欰I鐢熸垚浠爜 + 鐪熷疄鎵ц<E98EB5> + 琛ㄦ牸鍒锋柊鏄<E69F8A>樊寮傚寲浠峰€?

V1.1锛?025-12-06锛? 鏋舵瀯鍚堣<E98D9A>鎬т慨姝?鈿狅笍 閲嶈<E996B2>

**淇<><E6B787>鍐呭<E98D90>**锛氭牴鎹<E789B4>敤鎴蜂弗鑲冩彁閱掞紝淇<E7B49D><E6B787>浠ヤ笅杩濆弽瑙勮寖鐨勯棶棰橈細

<EFBFBD><EFBFBD>1锛氬己鍒跺<EFBFBD>鐢ㄥ钩鍙拌兘鍔?鉁?

  • **鍘熼敊璇?*锛氬缓璁<E7BC93>嚜宸卞疄鐜癝ession绠悊銆佸瓨鍌ㄣ€佹棩蹇?
  • **宸蹭慨姝?*锛氬己鍒朵娇鐢╜storage, logger, cache, prisma, LLMFactory`
  • 褰卞搷绔犺妭锛氭墍鏈塂ay 1-15鐨勪唬鐮佺ず渚?

<EFBFBD><EFBFBD>2锛歋ession瀛樺偍鏂瑰紡 鉁?

  • **鍘熼敊璇?*锛氬缓璁<E7BC93>Map<sessionId, data>鍐呭瓨缂撳瓨
  • **宸蹭慨姝?*锛歋ession瀛樻暟鎹<E69A9F>簱锛坄dc_tool_c_sessions`琛<>
  • 鍘熷洜锛氳繚鍙嶄簯鍘熺敓瑙勮寖绗?鏉★紙绂佹<E7BB82>鍐呭瓨缂撳瓨锛?

<EFBFBD><EFBFBD>3锛氭枃浠跺す缁撴瀯 鉁?

  • **鍘熼敊璇?*锛氬缓璁<E7BC93>垱寤篳python-service/銆乣node-service/瀛愭枃浠跺す
  • **宸蹭慨姝?*锛氶伒寰猼ool-b缁撴瀯锛坄services/, controllers/, routes/`锛?
  • **鍙傝€?*锛歚backend/src/modules/dc/tool-b/`

<EFBFBD><EFBFBD>4锛氭妧鏈<EFBFBD>爤璇存槑 鉁?

  • **鍘熼敊璇?*锛氭湭寮鸿皟澶嶇敤鐜版湁鑳藉姏
  • **宸蹭慨姝?*锛氭槑纭<E6A791>爣娉?宸叉湁"銆?澶嶇敤骞冲彴鑳藉姏"
  • **鏂板<E98F82>**锛氫簯鍘熺敓寮€鍙戣<E98D99>鑼冩<E991BC>鏌ユ竻鍗?

<EFBFBD><EFBFBD>5锛氫唬鐮佺ず渚?鉁?

  • **鍘熼敊璇?*锛欴ay 1-5鐨勪唬鐮佺ず渚嬫湭浣撶幇骞冲彴鏈嶅姟
  • **宸蹭慨姝?*锛氭墍鏈変唬鐮佺ず渚嬮兘浣跨敤import { storage } from '@/common/storage'绛?
  • **鏂板<E98F82>**锛氬父瑙侀敊璇<E6958A>ず渚嬶紙鉂?涓ョ<E6B693>锛?

鏂板<EFBFBD>绔犺妭 鉁?

  • **寮€鍙戝墠蹇呰<E8B987>**锛氬己璋冧笉瑕侀噸澶嶉€犺疆瀛?
  • **浜戝師鐢熻<E990A2>鑼冨己鍒惰<E98D92>姹?*锛氬垪鍑?鏉℃牳蹇冭<E8B987>鑼?
  • 甯歌<EFBFBD>閿欒<EFBFBD>绀轰緥锛氬睍绀?涓<>弗绂佺殑閿欒<E996BF>鍐欐硶

鏂囨。鐘舵€侊細 鉁?宸插畬鎴愶紙V1.1 鏋舵瀯鍚堣<E98D9A>鎬т慨姝増锛? 涓嬩竴姝ワ細 鍥㈤槦Review 鈫?涓ユ牸鎸夎<E98EB8>鑼冨紑鍙? 璐熻矗浜猴細 椤圭洰缁忕悊
*鍒涘缓鏃ユ湡锛? 2025-12-06
*<EFBFBD><EFBFBD>鏃ユ湡锛? 2025-12-06锛堟灦鏋勫悎瑙勬€т慨姝

鈿狅笍 閲嶈<E996B2>鎻愰啋锛?

  1. 寮€鍙戝墠蹇呴』闃呰<EFBFBD>锛歚docs/04-寮€鍙戣<E98D99>鑼?08-浜戝師鐢熷紑鍙戣<E98D99>鑼?md`
  2. 鍙傝€冪幇鏈夊疄鐜帮細backend/src/modules/dc/tool-b/
  3. 绂佹<EFBFBD>杩濆弽瑙勮寖锛氬唴瀛樼紦瀛樸€佹湰鍦版枃浠跺瓨鍌ㄣ€侀噸澶嶅疄鐜板钩鍙拌兘鍔?