ソースを参照

update: new chat

17870762608 2 ヶ月 前
コミット
d26f5c2318

+ 18 - 0
mcbridge-app/src/agent/agent-user-input/agent-user-input.component.html

@@ -0,0 +1,18 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-button color="medium" (click)="cancel()">取消</ion-button>
+    </ion-buttons>
+    <ion-title>用户输入</ion-title>
+    <ion-buttons slot="end">
+      <ion-button (click)="confirm()" [strong]="true">确认</ion-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+<ion-content class="ion-padding">
+  @for(field of fieldsArray;track field.name){
+    <ion-item>
+      <ion-input labelPlacement="stacked" label="请输入 {{field.name}}" [(ngModel)]="inputData[field.name]" placeholder="{{field.desc}}"></ion-input>
+    </ion-item>
+  }
+</ion-content>

+ 0 - 0
mcbridge-app/src/agent/agent-user-input/agent-user-input.component.scss


+ 22 - 0
mcbridge-app/src/agent/agent-user-input/agent-user-input.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { AgentUserInputComponent } from './agent-user-input.component';
+
+describe('AgentUserInputComponent', () => {
+  let component: AgentUserInputComponent;
+  let fixture: ComponentFixture<AgentUserInputComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      imports: [AgentUserInputComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(AgentUserInputComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 38 - 0
mcbridge-app/src/agent/agent-user-input/agent-user-input.component.ts

@@ -0,0 +1,38 @@
+import { Component, OnInit, Input } from '@angular/core';
+import { ModalController, IonHeader, IonContent, IonInput, IonToolbar, IonItem, IonButtons, IonButton, IonTitle } from '@ionic/angular/standalone';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+export interface AgentUserInputField{
+  name:string, // 字段名称
+  type:string, // 输入类型
+  desc:string, // 字段说明
+}
+@Component({
+  selector: 'agent-user-input',
+  templateUrl: './agent-user-input.component.html',
+  styleUrls: ['./agent-user-input.component.scss'],
+  standalone: true,
+  imports:[
+    IonHeader,IonContent,IonInput,IonToolbar,IonItem,IonButtons,IonButton,
+    IonTitle,
+    FormsModule,ReactiveFormsModule,
+  ]
+})
+export class AgentUserInputComponent  implements OnInit {
+
+  @Input()
+  fieldsArray:AgentUserInputField[]=[]
+
+  @Input()
+  inputData:any = {}
+
+  constructor(private modalCtrl: ModalController) {}
+  ngOnInit(){
+  }
+  cancel() {
+    return this.modalCtrl.dismiss(null, 'cancel');
+  }
+
+  confirm() {
+    return this.modalCtrl.dismiss(this.inputData, 'confirm');
+  }
+}

+ 23 - 0
mcbridge-app/src/agent/agent.input.ts

@@ -0,0 +1,23 @@
+import { ModalController } from '@ionic/angular/standalone';
+import { AgentUserInputComponent } from './agent-user-input/agent-user-input.component';
+
+/**
+ * 数据搜集Modal
+ * @description
+ * https://ionicframework.com/docs/api/modal#controller-modals
+ */
+export async function getUserInput(modalCtrl:ModalController,options:{fieldsArray:any}){
+  const modal = await modalCtrl.create({
+    component: AgentUserInputComponent,
+    componentProps:{
+      fieldsArray:options.fieldsArray
+    }
+  });
+  modal.present();
+
+  const { data, role } = await modal.onWillDismiss();
+
+  if (role === 'confirm') {
+    return data;
+  }
+}

+ 44 - 0
mcbridge-app/src/agent/agent.json.ts

@@ -0,0 +1,44 @@
+/**
+ * 
+ 结果是:
+ {
+     "keshi":"呼吸科",
+     "user":{
+         "name":""
+     }
+ }
+ */
+ export function extactAndParseJsonFromString(inputString:string){
+    let startIndex = inputString.indexOf("{")
+    if(startIndex==-1) return {}
+
+    let count = 0;
+    let endIndex = startIndex;
+
+    // 遍历字符串,计算花括号实现数量平衡
+    for (let i = startIndex; i < inputString.length; i++) {
+        // console.log(i,inputString[i])
+        if(inputString[i]==="{"){
+            count++;
+        }else if(inputString[i]==="}"){
+            count--;
+        }
+        // 当花括号平衡,我们找到了完整的JSON
+        if(count === 0){
+            endIndex = i;
+            break;
+        }
+    }
+    // 若不平衡
+    if(count!=0) return {};
+
+    // 提取JSON字符串,并解析
+    const jsonString = inputString.slice(startIndex,endIndex+1);
+    console.log("jsonString",jsonString)
+    try{
+        return JSON.parse(jsonString);
+    }catch(error){
+        console.error("Failed to parse JSON",error);
+        return {}
+    }
+ }

+ 21 - 0
mcbridge-app/src/agent/agent.start.ts

@@ -0,0 +1,21 @@
+import { AgentTaskStep } from "./agent.task";
+
+/**
+ * 任务执行函数
+ */
+export async function TaskExecutor(taskStepList:AgentTaskStep[]){
+
+for (let index = 0; index < taskStepList.length; index++) {
+    let step = taskStepList[index];
+    let result = await step.handle()
+    if(result == false) {break;} 
+
+    if(step.error){
+        break;
+    }
+    if(!step.error){ // 任务执行正常,无Error
+
+    }
+}
+
+}

+ 94 - 0
mcbridge-app/src/agent/agent.task.ts

@@ -0,0 +1,94 @@
+
+// 任务步骤初始化参数
+interface AgentTaskStepOptions{
+    title:string
+    shareData?:any
+    handle?():{():Promise<any>}
+}
+
+export class AgentTaskStep{
+    // 任务名称
+    title:string = ""
+
+    // 任务数据 共享数据(整个任务集共享传递的数据)
+    shareData:any = {}
+    // 任务数据 私有数据(当前任务私有的处理数据)
+    data:any = {}
+
+    // 父级组件:任务集组件
+    // @example 当前子任务未完成,且当前任务是必须时,需要在当前任务中,终止整个程序
+    parentComp:any|undefined
+    // 当前任务在任务集数组中的项目
+    parentIndex:number|undefined
+
+    /**
+     * 任务生命周期
+     * @constructor // 构造时执行一次
+     * @onInit // 初始化后执行一次
+     * @onProgress // 进度变化时执行一次
+     * @onComplete // 完成前执行一次
+     */
+    constructor(metaData:AgentTaskStepOptions){
+        this.title = metaData.title
+        this.shareData = metaData.shareData
+        if(metaData.handle){
+            this.handle = metaData.handle
+        }
+        this.init(metaData)
+    }
+    onInit(step:AgentTaskStep){
+        this.isInit = true;
+    }
+    beforeHandle(step:AgentTaskStep){
+
+    }
+    afterHandle(step:AgentTaskStep){
+
+    }
+    onProgress(step:AgentTaskStep,progress:number){
+
+    }
+    onComplete(step:AgentTaskStep){
+
+    }
+    onError(step:AgentTaskStep){
+
+    }
+
+    /**
+     * 任务初始化函数
+     */
+    async init(metaData:AgentTaskStepOptions){
+    }
+    isInit:boolean = false; // 是否初始化
+
+    /** 
+     * 任务执行函数
+     * @desc 函数内必须有明确的完成、结束情形,函数内必须有进度的变化指示 progress从0.00 - 1.00
+     */
+    progress:number = 0;
+    // get progress(){
+    //     return this._progress
+    // }
+    // set progress(v:number){
+    //     this._progress = v
+    //     this.onProgress(this,this.progress)
+    // }
+
+    handle():Promise<any>|any{
+        this.beforeHandle(this)
+
+
+
+
+
+        this.onComplete(this)
+        this.onError(this)
+        return true
+    }
+
+    /**
+     * 任务错误提示
+     */
+    error:string = "" // 错误原因
+}

+ 64 - 0
mcbridge-app/src/agent/tasks/inquiry/1.inquiry-user-story.ts

@@ -0,0 +1,64 @@
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { getUserInput } from 'src/agent/agent.input';
+import { ModalController } from '@ionic/angular/standalone';
+import { FmodeChatCompletion } from 'fmode-ng';
+import { extactAndParseJsonFromString } from 'src/agent/agent.json';
+
+export function TaskInqueryUserStory(options:{
+    modalCtrl:ModalController
+    shareData:any}
+    ):AgentTaskStep{
+        let task1 = new AgentTaskStep({title:"导诊:根据患者描述导诊对应科室",shareData:options.shareData})
+        task1.handle = ()=>{
+            return new Promise(async (resolve,reject)=>{
+                // 获取用户输入的诗词
+                let userInput = await getUserInput(options.modalCtrl,{fieldsArray:[
+                    {name:"症状口述",type:"text",desc:"描述下感觉到的症状或不适。"}
+                ]});
+
+                if(!userInput?.['症状口述']){
+                    task1.error = "无症状口述,无法判断科室"
+                    resolve(false);
+                }
+
+                // 文本生成
+                let PromptTemplate = `您是一名专业的医护人员,在门诊大厅负责导诊服务,请您根据患者的症状口述,为其选择合适的科室进行挂号。
+                患者症状口述:${userInput['症状口述']}
+                结果以JSON格式表示:
+                症状名称为具体的症状,症状描述为用户的感受,持续时间若没有直接说,可以写近期即可。
+                {
+                    "keshi":"科室名称",
+                    "sympList":[
+                        {"title":"症状名称","desc":"症状描述","duration":"持续时间"}
+                    ]
+                }
+                `
+                let completion = new FmodeChatCompletion([
+                    {role:"system",content:""},
+                    {role:"user",content:PromptTemplate}
+                    ])
+                    completion.sendCompletion().subscribe((message:any)=>{
+                        if(task1.progress < 0.5){
+                            task1.progress += 0.1
+                        }
+                        if(task1.progress >= 0.5 && task1.progress <= 0.9){
+                            task1.progress += 0.01
+                        }
+                        if(task1.progress >= 0.9){
+                            task1.progress += 0.001
+                        }
+                        // 打印消息体
+                        console.log(message.content)
+                        // 赋值消息内容给组件内属性
+                        if(message.complete){ // 判断message为完成状态,则设置isComplete为完成
+                            options.shareData.userStory = extactAndParseJsonFromString(message.content)
+                            options.shareData.userStory['症状口述'] = userInput['症状口述']
+                            task1.progress = 1
+                            resolve(true)
+                        }
+                })
+            })
+
+        }
+        return task1
+}

+ 79 - 0
mcbridge-app/src/agent/tasks/inquiry/2.inquiry-doctor-question.ts

@@ -0,0 +1,79 @@
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { getUserInput } from 'src/agent/agent.input';
+import { ModalController } from '@ionic/angular/standalone';
+import { FmodeChatCompletion } from 'fmode-ng';
+import { extactAndParseJsonFromString } from 'src/agent/agent.json';
+
+export function TaskInqueryDoctorQuestion(options:{
+    modalCtrl:ModalController
+    shareData:any}
+    ):AgentTaskStep{
+        /**
+         shareData.userStory // 已经拥有的用户描述数据
+         {
+                  "keshi": "神经内科",
+                  "sympList": [
+                      {
+                          "title": "偏头痛",
+                          "desc": "持续了2天的偏头疼",
+                          "duration": "2天"
+                      },
+                      {
+                          "title": "发冷",
+                          "desc": "感觉发冷,已经有一天",
+                          "duration": "1天"
+                      }
+                  ]
+              }
+         */
+        let task1 = new AgentTaskStep({title:"问诊:医生根据患者情况,主动询问",shareData:options.shareData})
+        task1.handle = ()=>{
+            return new Promise(async (resolve,reject)=>{
+                // 获取用户输入
+                // let userInput = await getUserInput(options.modalCtrl,{fieldsArray:[
+                //     {name:"症状口述",type:"text",desc:"描述下感觉到的症状或不适。"}
+                // ]});
+
+                // if(!userInput?.['症状口述']){
+                //     task1.error = "无症状口述,无法判断科室"
+                //     resolve(false);
+                // }
+
+                // 文本生成
+                let PromptTemplate = `您是一名专业的${options.shareData.userStory.keshi}主任医生,患者简单描述了一下他的情况,请您思考下还有哪些需要询问。
+                症状口述:${options.shareData.userStory['症状口述']}
+                结果以JSON格式表示:
+                {
+                    "questionList":[
+                        {"title":"问题标题","desc":"问题描述"}
+                    ]
+                }
+                `
+                let completion = new FmodeChatCompletion([
+                    {role:"system",content:""},
+                    {role:"user",content:PromptTemplate}
+                    ])
+                    completion.sendCompletion().subscribe((message:any)=>{
+                        if(task1.progress < 0.5){
+                            task1.progress += 0.1
+                        }
+                        if(task1.progress >= 0.5 && task1.progress <= 0.9){
+                            task1.progress += 0.01
+                        }
+                        if(task1.progress >= 0.7){
+                            task1.progress += 0.001
+                        }
+                        // 打印消息体
+                        console.log(message.content)
+                        // 赋值消息内容给组件内属性
+                        if(message.complete){ // 判断message为完成状态,则设置isComplete为完成
+                            options.shareData.userStory.questionList = extactAndParseJsonFromString(message.content).questionList || []
+                            task1.progress = 1
+                            resolve(true)
+                        }
+                })
+            })
+
+        }
+        return task1
+}

+ 141 - 0
mcbridge-app/src/agent/tasks/inquiry/3.inquiry-user-answer.ts

@@ -0,0 +1,141 @@
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { getUserInput } from 'src/agent/agent.input';
+import { ModalController } from '@ionic/angular/standalone';
+import { FmodeChatCompletion } from 'fmode-ng';
+import { extactAndParseJsonFromString } from 'src/agent/agent.json';
+
+export function TaskInqueryUserAnswer(options:{
+    modalCtrl:ModalController
+    shareData:any}
+    ):AgentTaskStep{
+        /**
+         shareData.userStory // 已经拥有的医生主动询问
+         {
+            "questionList": [
+                {
+                    "title": "头痛的性质",
+                    "desc": "请问您的偏头痛是怎样的感觉?是刺痛、跳动还是压迫感?"
+                },
+            ]
+        }
+         */
+        let task1 = new AgentTaskStep({title:"诊断:患者回答具体内容后,医生给出诊断结果",shareData:options.shareData})
+        task1.handle = ()=>{
+            return new Promise(async (resolve,reject)=>{
+                // 获取用户输入的问题清单
+                let questionList = options.shareData.userStory.questionList.map((item:any)=>{return {name:item.title,desc:item.desc,type:"text"}})
+                
+                let userInputResult = await getUserInput(options.modalCtrl,{fieldsArray:questionList});
+                console.log(userInputResult)
+                questionList.forEach((question:any)=>{
+                    question.answer = userInputResult[question.name]
+                })
+            
+                // 文本生成
+                let qaContent = options.shareData.userStory.questionList.map((item:any)=>`医生问:${item.title},${item.desc}\n患者答:${item.answer||"没回答"}`).join("\n")
+                let PromptTemplate = `您是一名专业的${options.shareData.userStory.keshi}主任医生,根据具体的询问,给出初步诊断。
+                症状口述:${options.shareData.userStory['症状口述']}
+                具体询问:${qaContent}
+                结果以JSON格式表示:
+                症状名称为具体的症状,症状描述为用户的感受,持续时间若没有直接说,可以写近期即可。
+                {
+                    "title":"病例标题",
+                    "desc":"病情概括",
+                    "content":"给出完整的治疗方案和建议"
+                }
+                `
+                let completion = new FmodeChatCompletion([
+                    {role:"system",content:""},
+                    {role:"user",content:PromptTemplate}
+                    ])
+                    completion.sendCompletion().subscribe((message:any)=>{
+                        if(task1.progress < 0.5){
+                            task1.progress += 0.1
+                        }
+                        if(task1.progress >= 0.5 && task1.progress <= 0.9){
+                            task1.progress += 0.01
+                        }
+                        if(task1.progress >= 0.9){
+                            task1.progress += 0.001
+                        }
+                        // 打印消息体
+                        console.log(message.content)
+                        // 赋值消息内容给组件内属性
+                        if(message.complete){ // 判断message为完成状态,则设置isComplete为完成
+                            options.shareData.diagResult = extactAndParseJsonFromString(message.content)
+                            task1.progress = 1
+                            resolve(true)
+                        }
+                })
+            })
+
+        }
+        return task1
+}
+
+
+const TestShareData = {
+userStory : {
+  "keshi": "神经内科",
+  "sympList": [
+      {
+          "title": "偏头疼",
+          "desc": "已经持续了2天了",
+          "duration": "2天"
+      },
+      {
+          "title": "发冷",
+          "desc": "感觉已经有一天",
+          "duration": "1天"
+      }
+  ],
+  "症状口述": "偏头疼已经持续了2天了,发冷感觉已经有一天。",
+  "questionList": [
+      {
+          "title": "头痛的性质",
+          "desc": "请描述您的头痛是搏动性、压迫性还是其他类型?",
+          "answer":"压迫性头疼"
+      },
+      {
+          "title": "头痛的部位",
+          "desc": "您的头痛主要集中在头部的哪个区域?",
+          "answer":"左侧头疼"
+      },
+      {
+          "title": "伴随症状",
+          "desc": "除了头痛和发冷,您还有其他的症状吗?例如恶心、呕吐、视力模糊或对光敏感等?",
+          "answer":"有点恶心但是没有呕吐"
+      },
+      {
+          "title": "发冷的性质",
+          "desc": "您感到发冷时是否伴随有发热、出汗或其他症状?",
+          "answer":"没有"
+      },
+      {
+          "title": "既往病史",
+          "desc": "您是否有偏头痛或其他头痛的病史?",
+          "answer":"没有"
+      },
+      {
+          "title": "生活习惯",
+          "desc": "您最近的生活习惯是否有变化?例如睡眠不足、压力增大或饮食不规律?",
+          "answer":"经常熬夜,学习压力大"
+      },
+      {
+          "title": "药物使用",
+          "desc": "您是否有服用任何药物来缓解头痛或其他症状?",
+          "answer":"没有"
+      },
+      {
+          "title": "家族病史",
+          "desc": "您的家族中是否有人有类似的头痛或神经系统疾病史?",
+          "answer":"没有"
+      },
+      {
+          "title": "过敏史",
+          "desc": "您是否有药物或其他物质的过敏史?",
+          "answer":"没有"
+      }
+  ]
+}
+}

+ 55 - 0
mcbridge-app/src/agent/tasks/poem/poem-desc.ts

@@ -0,0 +1,55 @@
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { getUserInput } from 'src/agent/agent.input';
+import { ModalController } from '@ionic/angular/standalone';
+import { FmodeChatCompletion } from 'fmode-ng';
+
+export function TaskPoemPictureDesc(options:{
+    modalCtrl:ModalController
+    shareData:any}
+    ):AgentTaskStep{
+        let task1 = new AgentTaskStep({title:"意境分析",shareData:options.shareData})
+        task1.handle = ()=>{
+            return new Promise(async (resolve,reject)=>{
+                // 获取用户输入的诗词
+                let userInput = await getUserInput(options.modalCtrl,{fieldsArray:[
+                    {name:"诗文内容",type:"text",desc:"诗文句子或段落"}
+                ]});
+                console.log("已获取用户输入:",userInput)
+                if(userInput){
+                    console.log("已获取诗文内容:",userInput['诗文内容'])
+                }
+                if(!userInput?.['诗文内容']){
+                    task1.error = "缺少诗文内容,请重新开始"
+                    resolve(false);
+                }
+
+                    // 文本生成
+                let PromptTemplate = `您是一名专业的美术画家,请您根据古诗文的内容,将其描述的画面、场景、人物、物品等用最简短的语言表达,直接写出画面,并且以中国的古风意境为主
+                诗文如下:
+                ${userInput['诗文内容']}
+                `
+                let completion = new FmodeChatCompletion([
+                    {role:"system",content:""},
+                    {role:"user",content:PromptTemplate}
+                    ])
+                    completion.sendCompletion().subscribe((message:any)=>{
+                        if(task1.progress < 0.5){
+                            task1.progress += 0.1
+                        }
+                        if(task1.progress >= 0.5){
+                            task1.progress += 0.01
+                        }
+                        // 打印消息体
+                        // console.log(message.content)
+                        // 赋值消息内容给组件内属性
+                        options.shareData.PictureDescResult = message.content
+                        if(message.complete){ // 判断message为完成状态,则设置isComplete为完成
+                            task1.progress = 1
+                            resolve(true)
+                        }
+                })
+            })
+
+        }
+        return task1
+}

+ 43 - 0
mcbridge-app/src/agent/tasks/poem/poem-picture.ts

@@ -0,0 +1,43 @@
+import { ModalController } from '@ionic/angular/standalone';
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { ImagineWork, DalleOptions } from 'fmode-ng';
+
+
+export function TaskPoemPictureCreate(options:{
+    modalCtrl:ModalController
+    shareData:any}):AgentTaskStep{
+    let task2 = new AgentTaskStep({title:"意境绘制",shareData:options.shareData})
+    task2.handle = ()=>{
+      return new Promise(resolve=>{
+        // let userInput = await getUserInput(options.modalCtrl,{fieldsArray:[
+        //   {name:"绘图要求",type:"text",desc:"画风、构图等等"}
+        // ]});
+        // console.log(userInput)
+        console.log("意境绘制:执行过程")
+
+        if(!options.shareData.PictureDescResult){
+          task2.error = "缺少古风描述结果,请重新执行。"
+          resolve(false)
+        }
+        let imagineWork = new ImagineWork();
+        // 图片生成
+        let PicturePrompt = `${options.shareData.PictureDescResult}\n风格:中国古风。画面不带任何文字。`
+        let imgOptions:DalleOptions = {prompt:PicturePrompt}
+        let countDownInt = setInterval(()=>{
+          task2.progress += 0.01
+        },1000)
+        imagineWork?.draw(imgOptions).subscribe((work:any)=>{
+            console.log("imagineWork",work?.toJSON())
+            console.log("images",work?.get("images"))
+            if(work?.get("images")?.length){
+              options.shareData.images = work?.get("images");
+              clearInterval(countDownInt);
+              task2.progress = 1
+              resolve(true)
+            }
+        })
+      })
+
+    }
+    return task2
+}

+ 47 - 7
mcbridge-app/src/app/tab2/tab2.page.html

@@ -1,17 +1,57 @@
 <ion-header [translucent]="true">
   <ion-toolbar>
     <ion-title>
-      Tab 2
+      任务集执行展示
     </ion-title>
   </ion-toolbar>
 </ion-header>
 
 <ion-content [fullscreen]="true">
-  <ion-header collapse="condense">
-    <ion-toolbar>
-      <ion-title size="large">Tab 2</ion-title>
-    </ion-toolbar>
-  </ion-header>
+ <ion-button (click)="doPoemTask()">执行诗文意境绘制任务集</ion-button>
+ <ion-button (click)="doInqueryTask()">执行问诊任务集</ion-button>
+  <ion-button (click)="testJSON()">测试JSON</ion-button>
+
+
+ <ul>
+  @for(step of taskList;track step.title;){
+    <div>
+      <!-- 待开始 -->
+      @if(step.progress==0 && !step.error){
+        <ion-icon name="radio-button-off-outline"></ion-icon>
+      }
+      <!-- 进行中 -->
+      @if(step.progress!=0 && step.progress!=1){
+        <ion-icon name="reload-outline"></ion-icon>
+      }
+      <!-- 已完成 -->
+      @if(step.progress==1){
+        <ion-icon name="checkmark-circle-outline"></ion-icon>
+      }
+      <!-- 已出错 -->
+      @if(step.error){
+        <ion-icon name="close-circle-outline"></ion-icon>
+      }
+      {{step.title}}  @if(step.progress){<span>{{step.progress * 100 | number:"2.0-0"}}%</span>}
+
+      @if(step.error){
+        <span style="color:red;">{{step.error}}</span>
+      }
+    </div>   
+  }
+  </ul>
+
+  <!-- 诗词意境绘画生成结果 -->
+  @if(shareData.images) {
+    @for(imageUrl of shareData.images;track imageUrl){
+      <img [src]="imageUrl" alt="" srcset="">
+    }
+  }
+
+  <!-- 问诊报告生成结果 -->
+  @if(shareData.diagResult){
+    <h1>{{shareData.diagResult.title}}</h1>
+    <h2>{{shareData.diagResult.desc}}</h2>
+    <p>{{shareData.diagResult.content}}</p>
+  }
 
-  <app-explore-container name="Tab 2 page"></app-explore-container>
 </ion-content>

+ 86 - 2
mcbridge-app/src/app/tab2/tab2.page.ts

@@ -1,16 +1,100 @@
 import { Component } from '@angular/core';
 import { IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/angular/standalone';
 import { ExploreContainerComponent } from '../explore-container/explore-container.component';
+import { extactAndParseJsonFromString } from 'src/agent/agent.json';
+import { TaskInqueryUserStory } from 'src/agent/tasks/inquiry/1.inquiry-user-story';
+import { TaskInqueryDoctorQuestion } from 'src/agent/tasks/inquiry/2.inquiry-doctor-question';
+import { TaskInqueryUserAnswer } from 'src/agent/tasks/inquiry/3.inquiry-user-answer';
+import { TaskExecutor } from 'src/agent/agent.start';
+import { AgentTaskStep } from 'src/agent/agent.task';
+import { IonButton, IonIcon, ModalController } from '@ionic/angular/standalone';
+import { TaskPoemPictureDesc } from 'src/agent/tasks/poem/poem-desc';
+import { TaskPoemPictureCreate } from 'src/agent/tasks/poem/poem-picture';
+import { DecimalPipe } from '@angular/common';
+import { addIcons } from 'ionicons';
+import { radioButtonOffOutline, reloadOutline, checkmarkCircleOutline, closeCircleOutline } from 'ionicons/icons';
 
+addIcons({radioButtonOffOutline, reloadOutline, checkmarkCircleOutline, closeCircleOutline}) 
 @Component({
   selector: 'app-tab2',
   templateUrl: 'tab2.page.html',
   styleUrls: ['tab2.page.scss'],
   standalone: true,
-  imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent]
+  imports: [IonHeader, IonToolbar, IonTitle, IonContent, ExploreContainerComponent, IonButton, IonIcon, DecimalPipe,
+  ]
 })
 export class Tab2Page {
 
-  constructor() {}
+  constructor(private modalCtrl:ModalController) {
+
+
+  }
+
+  taskList:AgentTaskStep[] = []
+
+  wait(duration:number=1000){
+    return new Promise(resolve=>{
+      setTimeout(() => {
+          resolve(true)
+      }, duration);
+    })
+  }
+
+  shareData:any = {}
+
+  // 任务:完成故事意境描述及图像绘制
+  doPoemTask(){
+    // 产生: shareData.PictureDescResult 生成后描述
+    let task1 = TaskPoemPictureDesc({shareData:this.shareData,modalCtrl:this.modalCtrl});
+    // 产生: shareData.images 渲染后图片
+    let task2 = TaskPoemPictureCreate({shareData:this.shareData,modalCtrl:this.modalCtrl});
+    
+    // 定义任务集
+    let PoemTaskList = [task1,task2]
+    // 传递给显示组件
+    this.taskList = PoemTaskList
+    // 开始执行任务
+    TaskExecutor(PoemTaskList)
+  }
+
+
+  testJSON(){
+    let string = `
+          ''''json
+              {
+                  "keshi": "神经内科",
+                  "sympList": [
+                      {
+                          "title": "偏头痛",
+                          "desc": "持续了2天的偏头疼",
+                          "duration": "2天"
+                      },
+                      {
+                          "title": "发冷",
+                          "desc": "感觉发冷,已经有一天",
+                          "duration": "1天"
+                      }
+                  ]
+              }
+              ''''
+      `
+      console.log(extactAndParseJsonFromString(string))
+  }
+  // 任务集:医疗问诊任务集 完成一次完整的门诊服务
+  doInqueryTask(){
+    let task1 = TaskInqueryUserStory({shareData:this.shareData,modalCtrl:this.modalCtrl});
+    let task2 = TaskInqueryDoctorQuestion({shareData:this.shareData,modalCtrl:this.modalCtrl});
+    let task3 = TaskInqueryUserAnswer({shareData:this.shareData,modalCtrl:this.modalCtrl});
+
+    // 定义任务集
+    let InquireServiceTaskList = [
+      task1,task2,task3
+    ]
+    // 传递给显示组件
+    this.taskList = InquireServiceTaskList
+    // 开始执行任务
+    TaskExecutor(InquireServiceTaskList)
+  }
+
 
 }

+ 2 - 2
mcbridge-prod/README.md

@@ -6,7 +6,7 @@
 
 # 一、项目设想
 ## 1.一句话描述项目设想
-创建一个能够自主学习、推理和解决问题的智能系统,根据用户的学习风格和进度定制个性化的学习路径,实现跨学科知识的整合,提供丰富的回答和建议,构建自然语言处理能力,促使用户可以用日常语言与系统互动.
+医护云桥”是一项旨在通过信息技术手段提升医疗服务效率和质量的创新项目。该项目主要依托云计算、大数据和人工智能等先进技术,建立一个综合性的医疗服务平台,连接患者、医护人员和医疗机构,实现信息的高效流通和资源的优化配置。
 ## 2.项目的业务流程
 - 目标用户调研:了解医护人员的学习需求、知识掌握程度、学习习惯及进度,识别痛点和需求,收集用户反馈,分析医疗行业的知识空白和知识更新需求。
 - 知识整合:将医学、护理、心理学等多学科的知识整合到平台,确保用户能获得全面、深刻的跨学科知识。
@@ -34,7 +34,7 @@
 ## 用户分析
 - 医护人员:包括医生、护士、药剂师等,主要需求是提升专业知识、技能和跨学科的协作能力。
 - 医学生:在校医学生需要获取最新的医学知识和临床技能,帮助他们更好地准备实习和未来的职业生涯。
-- 大众:帮助大家在家一些病状分析,即时处理,以及专家咨询
+- 患者:帮助大家在家一些病状分析,即时处理,以及专家咨询
 ## 主要功能
 - 自然语言处理与互动:实现语音识别和文本理解,允许用户通过自然语言提问和获取建议。
 - 专家咨询与答疑服务:用户可以通过平台提问,系统推荐相关专家进行解答,并提供按次收费的咨询服务。