Files
AIclinicalresearch/docs/03-业务模块/ADMIN-运营管理端/02-技术设计/03-Prompt管理系统快速参考.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

8.6 KiB
Raw Blame History

*Prompt蝞∠<EFBFBD>蝟餌<EFBFBD>敹恍<EFBFBD><EFBFBD><EFBFBD>?

*<EFBFBD><EFBFBD>𧋦嚗? v1.0
隡睃<EFBFBD>蝥改<EFBFBD> P0嚗<30>瓲敹<E793B2><E695B9>𡁶鍂<F0A181B6><EFBFBD>嚗? <EFBFBD><EFBFBD><EFBFBD><EFBFBD><><E695BA><EFBFBD>?


<EFBFBD><EFBFBD> <20><EFBFBD><EFBFBD>

<EFBFBD><EFBFBD>糓Prompt蝞∠<EFBFBD>蝟餌<EFBFBD>嚗?

<EFBFBD>銝芸<EFBFBD>霈?銝㮖<EFBFBD>鈭箏<EFBFBD><EFBFBD><EFBFBD>鈭抒㴓憓<EFBFBD><EFBFBD><EFBFBD><EFBFBD>霂𧭈I Prompt*<2A><><EFBFBD>摨阡<E691A8><EFBFBD>頂蝏麄<E89D8F>?

銝箔<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?

  • <EFBFBD>?**<2A>𤤿<EFBFBD>1嚗?* 瘚贝<E7989A><E8B49D><EFBFBD><E887AC><EFBFBD>璅⊥<E79285><E28AA5><EFBFBD><E7AC94>餃郎<E9A483>唳旿嚗?0蝭<30><E89DAD><EFBFBD><EFBFBD><E69FB4><EFBFBD>摰䂿<E691B0><E482BF><EFBFBD><EFBFBD>
  • <EFBFBD>?**<2A>𤤿<EFBFBD>2嚗?* 瘥𤩺活靚<E6B4BB>㟲Prompt<70><74><EFBFBD>㺿隞<E3BABF><E99A9E><EFBFBD><EFBFBD>蝵聆<E89DB5>蝑匧<E89D91>嚗?<3F><><EFBFBD>嚗?
  • <EFBFBD>?**<2A>𤤿<EFBFBD>3嚗?* 銝游<E98A9D>銝枏振<E69E8F><EFBFBD><E4ADBE><EFBFBD><EFBFBD><EFBFBD><E99D9A><EFBFBD><E59A97>隞砌<E99A9E>隡𡁜<E99AA1><EFBFBD><E99A9E>嚗?
  • <EFBFBD>?*<EFBFBD><EFBFBD>嚗? <20>煺漣<E785BA><EFBFBD><E887AC>啣漲憸<E6BCB2><E686B8> + 靚<><E99D9A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?+ DRAFT/ACTIVE<56><45>𧋦<EFBFBD>𠉛氖

<EFBFBD><EFBFBD>儭?<3F>唳旿摨廍chema

雿滨蔭嚗䫤capability_schema`

// --- Prompt Management System ---

model PromptTemplate {
  id          Int       @id @default(autoincrement())
  code        String    @unique                       // 'ASL_SCREENING_TitleAbstract'
  name        String                                  // "ASL<53><4C><EFBFBD><EFBFBD><EFBFBD>蝑偦<E89D91>?
  module      String                                  // ASL, DC, IIT, AIA, PKB, RVW
  description String?
  variables   Json?                                   // ["title", "abstract"]
  
  versions    PromptVersion[]

  createdAt   DateTime  @default(now()) @map("created_at")
  updatedAt   DateTime  @updatedAt @map("updated_at")

  @@map("prompt_templates")
  @@schema("capability_schema")
}

model PromptVersion {
  id          Int            @id @default(autoincrement())
  templateId  Int            @map("template_id")
  version     Int                                     // <20><>𧋦<EFBFBD>?
  content     String         @db.Text                 // Prompt<70><74>捆
  modelConfig Json?                                   // {"temperature": 0.1}
  status      PromptStatus   @default(DRAFT)
  changelog   String?                                 // "憓𧼮<E68693><EFBFBD><E988AD><EFBFBD><EFBFBD><E69697>?
  createdBy   String?        @map("created_by")      // UserID嚗<44>恣霈∴<E99C88>
  
  template    PromptTemplate @relation(fields: [templateId], references: [id])

  createdAt   DateTime       @default(now()) @map("created_at")

  @@map("prompt_versions")
  @@schema("capability_schema")
  
  @@index([templateId, status])
}

enum PromptStatus {
  DRAFT       // <20>厩阮嚗<E998AE><E59A97>Debug璅<E79285><E288AA><EFBFBD>嚗?
  ACTIVE      // <20>煺漣<E785BA><E6BCA3>𧋦
  ARCHIVED    // 敶埝﹝
  
  @@schema("capability_schema")
}

<EFBFBD><EFBFBD> <20><><EFBFBD>銝舘<E98A9D><E88898>?

<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

<EFBFBD><EFBFBD><EFBFBD> Code <EFBFBD>讛膩 <EFBFBD><EFBFBD>鍂閫坿𠧧
prompt:view <EFBFBD><EFBFBD>Prompt<EFBFBD>𡑒”<EFBFBD><EFBFBD><EFBFBD><EFBFBD>? SUPER_ADMIN, PROMPT_ENGINEER
prompt:edit <EFBFBD>𥕦遣/靽格㺿DRAFT<46><54>𧋦 SUPER_ADMIN, PROMPT_ENGINEER
prompt:debug 潃?*<EFBFBD><EFBFBD><EFBFBD>霂閙芋撘? SUPER_ADMIN, PROMPT_ENGINEER
prompt:publish <EFBFBD><EFBFBD>DRAFT<EFBFBD>𡒶CTIVE SUPER_ADMIN, PROMPT_ENGINEER

<EFBFBD><EFBFBD>閫坿𠧧

enum UserRole {
  SUPER_ADMIN      = 'SUPER_ADMIN',
  PROMPT_ENGINEER  = 'PROMPT_ENGINEER',    // <20><> <20><EFBFBD>閫坿𠧧
  HOSPITAL_ADMIN   = 'HOSPITAL_ADMIN',
  PHARMA_ADMIN     = 'PHARMA_ADMIN',
  USER             = 'USER'
}

<EFBFBD><EFBFBD> <20><EFBFBD>API

蝞∠<EFBFBD>蝡舀𦻖<EFBFBD>?

<EFBFBD><EFBFBD> 頝臬<EFBFBD> <EFBFBD><EFBFBD><EFBFBD> <EFBFBD>讛膩
GET /api/admin/prompts prompt:view <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>㗇芋<EFBFBD>?
GET /api/admin/prompts/:id prompt:view <EFBFBD><EFBFBD>霂行<EFBFBD>+<2B><><EFBFBD><E89FAE>𧋦
POST /api/admin/prompts/draft prompt:edit 靽嘥<EFBFBD><EFBFBD>厩阮
POST /api/admin/prompts/publish prompt:publish <EFBFBD><EFBFBD>
POST /api/admin/prompts/debug prompt:debug *<EFBFBD><EFBFBD><EFBFBD>霂閙芋撘?

銝𡁜𦛚璅<EFBFBD><EFBFBD><EFBFBD><EFBFBD>

// backend/src/modules/asl/services/screening.service.ts

import { promptService } from '@/common/capabilities/prompt/prompt.service';

export class ScreeningService {
  async screenPaper(paper: any, userId: string) {
    // <20><20><EFBFBD><EFBFBD>鍂嚗朞䌊<E69C9E><EFBFBD><E585B8><EFBFBD><EFBFBD>摨阡<E691A8><EFBFBD>
    const prompt = await promptService.get(
      'ASL_SCREENING_TitleAbstract',
      { title: paper.title, abstract: paper.abstract },
      userId   // 潃?敹<>◆隡惩<E99AA1>userId
    );

    return await llmGateway.chat(prompt);
  }
}

<EFBFBD><20>滨垢蝏<E59EA2>

<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?

// frontend-v2/src/modules/admin/components/PromptDebugSwitch.tsx

export const PromptDebugSwitch = () => {
  const { hasPermission } = usePermission();
  const [debugMode, setDebugMode] = useState(false);
  
  if (!hasPermission('prompt:debug')) {
    return null;  // <20><> <20><><EFBFBD><EFBFBD><EFBFBD>
  }
  
  return (
    <>
      <Switch 
        checked={debugMode} 
        onChange={(enabled) => api.post('/api/admin/prompts/debug', { enabled })}
        checkedChildren="<22><><><E99D9A><E79285>"
        unCheckedChildren="<22>煺漣璅<E79285>"
      />
      {debugMode && (
        <Alert
          type="warning"
          message="<22>𩤃<EFBFBD><><E99D9A><E79285>撌脣<E6928C><E884A3><EFBFBD><E88D94><EFBFBD><E585B8>齿迤<E9BDBF>其蝙<E585B6><EFBFBD>蝔輻<E89D94>嚗㇄RAFT嚗㗇<E59A97>蝷箄<E89DB7>"
          banner
        />
      )}
    </>
  );
};

<EFBFBD><EFBFBD> 瘨匧<E798A8><E79285>

<EFBFBD> <EFBFBD><EFBFBD><EFBFBD>箸艶 憭齿<EFBFBD>摨? 隡睃<EFBFBD>蝥?
ASL <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝑䜘<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? 潃鐥<EFBFBD>潃鐥<EFBFBD>潃? P0
DC Tool B<>𣂼<EFBFBD><F0A382BC><EFBFBD>ool C皜<43><E79A9C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E89D92>瘚? 潃鐥<EFBFBD>潃鐥<EFBFBD>潃? P0
IIT 韐冽綉璉<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? 潃鐥<EFBFBD>潃鐥<EFBFBD>潃? P1
PKB RAG<EFBFBD><EFBFBD><EFBFBD><EFBFBD>鸌憭<EFBFBD><EFBFBD><EFBFBD><EFBFBD> 潃鐥<EFBFBD>潃鐥<EFBFBD> P1
AIA 10+<2B><EFBFBD>雿瓐<E99BBF><E79390><EFBFBD><EFBFBD><EFBFBD><E69B87>? 潃鐥<EFBFBD>潃? P2
RVW <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? 潃鐥<EFBFBD>潃? P2

<EFBFBD><EFBFBD> <20><EFBFBD><E8A9A8><EFBFBD>嚗㇊romptService嚗?

// backend/src/common/capabilities/prompt/prompt.service.ts

export class PromptService {
  private debugUsers = new Set<string>();        // <20><><EFBFBD>摮睃<E691AE><EFBFBD><E99D9A><EFBFBD><EFBFBD>
  private activeCache = new Map<string, string>(); // ACTIVE<56><45>𧋦蝻枏<E89DBB>
  
  // 霈曄蔭靚<E894AD><E99D9A><E79285>
  async setDebugMode(userId: string, enabled: boolean) {
    if (enabled) {
      this.debugUsers.add(userId);
    } else {
      this.debugUsers.delete(userId);
    }
  }
  
  // <20><EFBFBD>Prompt嚗<74><E59A97>摨行瓲敹<E793B2><E695B9>
  async get(code: string, variables: any, userId: string): Promise<string> {
    // 1. 靚<><E99D9A><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>靝RAFT<46><54>𧋦
    if (this.debugUsers.has(userId)) {
      const draft = await this.getDraftVersion(code);
      if (draft) {
        return this.render(draft.content, variables);
      }
    }
    
    // 2. <20><EFBFBD>𡁶鍂<F0A181B6>瑁繮<E79181>䨝CTIVE<56><45>𧋦嚗<F0A78BA6>蒂蝻枏<E89DBB>嚗?
    let active = this.activeCache.get(code);
    if (!active) {
      const version = await prisma.promptVersion.findFirst({
        where: { 
          template: { code },
          status: 'ACTIVE'
        },
        orderBy: { version: 'desc' }
      });
      active = version?.content || this.getFallback(code);
      this.activeCache.set(code, active);
    }
    
    return this.render(active, variables);
  }
  
  // Postgres LISTEN/NOTIFY <20>剜凒<E5899C>?
  async initHotReload() {
    const client = await pool.connect();
    await client.query('LISTEN prompt_update');
    
    client.on('notification', (msg) => {
      this.activeCache.clear();  // 皜<>征蝻枏<E89DBB>
    });
  }
}

<EFBFBD><EFBFBD><><E69298>𤏸恣<F0A48FB8>?

Phase 0: <20><EFBFBD>霈暹鴌嚗?憭抬<E686AD>

  • <EFBFBD>𥕦遣<EFBFBD>唳旿摨栞”嚗Ǒprompt_templates, prompt_versions`嚗?
  • 瘛餃<EFBFBD>prompt:*<EFBFBD><EFBFBD><EFBFBD><EFBFBD>躬platform_schema.permissions`
  • <EFBFBD>𥕦遣PROMPT_ENGINEER閫坿𠧧
  • 摰䂿緵PromptService<EFBFBD><EFBFBD><EFBFBD><EFBFBD>

Phase 1: 餈鞱𨯫蝡烘VP嚗?憭抬<E686AD>

  • <EFBFBD>滨垢蝞∠<EFBFBD><EFBFBD>屸𢒰嚗<EFBFBD><EFBFBD>銵具<EFBFBD><EFBFBD><EFBFBD>颲穃膥<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
  • <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>隞?
  • <EFBFBD>厩阮靽嘥<EFBFBD>/<2F><EFBFBD><E7A983><EFBFBD>

Phase 2: 銝𡁜𦛚璅<E79285><E288AA><EFBFBD><EFBFBD><E59A97>銝𡁜𦛚撘<F0A69B9A><E69298>𡢅<EFBFBD>

  • ASL璅<EFBFBD><EFBFBD>promptService.get()
  • DC璅<EFBFBD><EFBFBD>promptService.get()
  • <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

<EFBFBD><EFBFBD> 摰匧<E691B0>銝𡡞<E98A9D><F0A1A19E>?

<EFBFBD><EFBFBD><EFBFBD><EFBFBD>𠉛氖

  • <EFBFBD>?銝交聢璉<E881A2><E79289>匝prompt:debug`<60><><EFBFBD>
  • <EFBFBD>?靚<><E99D9A><E79285><E288AA><EFBFBD><E59786><EFBFBD><EFBFBD>典銁<E585B8><E98A81><EFBFBD><EFBFBD><EFBFBD>箄䌊<E7AE84>典仃<E585B8><E4BB83><EFBFBD>

摰∟恣<EFBFBD><EFBFBD>

  • <EFBFBD>?PromptVersion.createdBy霈啣<EFBFBD>靽格㺿鈭?
  • <EFBFBD>?AdminOperationLog霈啣<EFBFBD><EFBFBD><EFBFBD>銵䔶蛹嚗éodule='prompt'嚗?

<EFBFBD>𨅯<EFBFBD><EFBFBD><EFBFBD>

  • <EFBFBD>?隞<><E99A9E>銝凋<E98A9D><E5878B>䆲ardcoded Prompt雿靝蛹蝟餌<E89D9F>蝥批<E89DA5>摨?
  • <EFBFBD>?<3F>唳旿摨𤘪䰻霂仃韐交𧒄餈𥪜<E9A488>暺䁅恕<E48185><E68195>𧋦

<EFBFBD><20><EFBFBD>撌乩<E6928C>瘚?

  1. *<EFBFBD>箸艶嚗? 銝游<E98A9D>銝枏振Dr. Wang閫匧<E996AB>ASL<53><4C>讃蝑偦<E89D91><EFBFBD>蝖桃<E89D96>銝滚<E98A9D>

  2. *靽格㺿嚗? Dr. Wang<6E><EFBFBD>餈鞱𨯫蝞∠<E89D9E>蝡荔<E89DA1>靽格㺿ASL_SCREENING<EFBFBD><EFBFBD>rompt嚗<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>靽嘥<EFBFBD><EFBFBD>厩阮

  3. *<EFBFBD><EFBFBD>嚗? Dr. Wang<6E>孵稬憿園<E686BF><E59C92>?撘<><E69298><EFBFBD>霂閙芋撘?

  4. *撉諹<EFBFBD>嚗? Dr. Wang<6E><67><EFBFBD>蚊SL銝𡁜𦛚憿菟𢒰嚗䔶<E59A97>隡惩<E99AA1><EFBFBD><E89DAD><EFBFBD><EFBFBD><E6BBA8><EFBFBD><E597B5><EFBFBD>
    <EFBFBD>?蝟餌<E89D9F><E9A48C>𡒊垢璉<E59EA2>瘚见<E7989A>Dr. Wang<6E>求ebug<75>𡑒”銝哨<E98A9D><E593A8>㰘蝸DRAFT<46>㇊rompt

  5. *蝖株恕嚗? <20>𤑳緵蝏𤘪<E89D8F><EFBFBD>鈭?

  6. *<EFBFBD><EFBFBD>嚗? Dr. Wang<6E>𧼮<EFBFBD>蝞∠<E89D9E>憿蛛<E686BF><E89B9B>孵稬"<22><EFBFBD>"

  7. *蝏𤘪<EFBFBD>嚗? Dr. Wang<6E>喲𡡒靚<F0A1A192><E99D9A><E79285>


<EFBFBD><EFBFBD> <20><EFBFBD><E8A9A8><EFBFBD>

  • 02-<2D>𡁶鍂<F0A181B6><EFBFBD><EFBFBD>07-餈鞱𨯫銝擧㦤<E693A7><E3A6A4><EFBFBD><E681A3>垢PRD_v2.1.md - <20><EFBFBD><E9A2B1><EFBFBD>瘙?
  • 02-<2D>𡁶鍂<F0A181B6><EFBFBD><EFBFBD>03-Prompt蝞∠<E89D9E>蝟餌<E89D9F>銝𡒊<E98A9D>摨阡<E691A8><EFBFBD>挽霈⊥䲮獢?md - 霂衣<E99C82>霈曇恣
  • 00-<2D><><EFBFBD>銝舘<E98A9D><E88898><EFBFBD>蝟餅<E9A485><EFBC94>𥁒<EFBFBD>𠽤v1.0.md - <20><EFBFBD>璇喟<E79287>

<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>憪见<E686AA><E8A781><EFBFBD><E79DB2><EFBFBD>