فهرست منبع

update: AIpicture is implemented by taskchain in taskchain-page & taskchain-page and aipicture-page have the same function

cyx 4 ماه پیش
والد
کامیت
c556830559

+ 19 - 0
TFPower-app/src/app/agent/agent-userinput/agent-userinput.component.html

@@ -0,0 +1,19 @@
+<ion-header>
+  <ion-toolbar>
+    <ion-buttons slot="start">
+      <ion-button color="medium" (click)="cancel()">取消</ion-button>
+    </ion-buttons>
+    <ion-title>TaskChain for AIpicture</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)]="userInputData[field.name]"
+      placeholder="{{field.placeholder}}"></ion-input>
+  </ion-item>
+  }
+</ion-content>

+ 0 - 0
TFPower-app/src/app/agent/agent-userinput/agent-userinput.component.scss


+ 22 - 0
TFPower-app/src/app/agent/agent-userinput/agent-userinput.component.spec.ts

@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+
+import { AgentUserinputComponent } from './agent-userinput.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();
+  });
+});

+ 55 - 0
TFPower-app/src/app/agent/agent-userinput/agent-userinput.component.ts

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

+ 7 - 6
TFPower-app/src/app/agent/agent.task.ts

@@ -12,6 +12,13 @@ export class AgentTaskStep {
   // 私有数据
   data: any = {};
 
+  /**
+   * 任务初始化函数
+   * 因为构造器里不能执行异步函数,而metaData里传进来的数据中可能有需要异步处理的函数
+   */
+  isInit: boolean = false;
+  async init(metaData: AgentTaskStepOptions) {}
+
   // 父级组件
   parentComp: any | undefined;
   parentIndex: number | undefined;
@@ -41,12 +48,6 @@ export class AgentTaskStep {
   onComplete(step: AgentTaskStep) {}
   onError(step: AgentTaskStep) {}
 
-  /**
-   * 任务初始化函数
-   * 因为构造器里不能执行异步函数,而metaData里传进来的数据中可能有需要异步处理的函数
-   */
-  isInit: boolean = false;
-  async init(metaData: AgentTaskStepOptions) {}
   /**
    * 执行任务
    * @desc 函数内必须有明确的完成、结束情形和函数进度变化指示

+ 2 - 2
TFPower-app/src/app/page/aipicture-page/aipicture-page.component.html

@@ -28,6 +28,8 @@
     </ion-list>
   </ion-card>
 
+
+  <!-- 生成的图片 -->
   <ion-card color="light">
     <ion-card-header>
       <ion-card-title>生成图片</ion-card-title>
@@ -54,6 +56,4 @@
     </ion-list>
   </ion-card>
 
-
-
 </ion-content>

+ 2 - 2
TFPower-app/src/app/page/aipicture-page/aipicture-page.component.ts

@@ -59,8 +59,6 @@ export class AipicturePageComponent implements OnInit {
   }
 
   async createImage() {
-    this.imagineWork = new ImagineWork();
-
     // ai生成更详细的内容
     let PromptTemplate = `请您作为一名专业的美术大家,请根据以下需求给出更详细的补充,用最少的文字表达出来。需求有:${this.needs}`;
     console.log(PromptTemplate);
@@ -79,6 +77,8 @@ export class AipicturePageComponent implements OnInit {
       if (message?.complete) {
         console.log(this.PictureDescResult);
 
+        // ai生成图片
+        this.imagineWork = new ImagineWork();
         let PicturePrompt = `${this.PictureDescResult}风格,画面不带任何文字。`;
         let options: DalleOptions = { prompt: PicturePrompt };
         this.imagineWork?.draw(options).subscribe((work) => {

+ 26 - 0
TFPower-app/src/app/page/taskchain-page/taskchain-page.component.html

@@ -4,6 +4,12 @@
   </ion-toolbar>
 </ion-header>
 <ion-content [fullscreen]="true">
+  <ion-card color="medium">
+    <ion-card-header>
+      <ion-card-title>AI小助手</ion-card-title>
+      <ion-card-subtitle>填写以下信息,我来给你生成图片。</ion-card-subtitle>
+    </ion-card-header>
+  </ion-card>
   <ion-button (click)="createTask()">运行</ion-button>
 
   @for(task of taskList; track task.title){
@@ -25,4 +31,24 @@
   </ion-card>
   }
 
+
+  <!-- 生成的图片 -->
+  <ion-card color="light">
+    <ion-card-header>
+      <ion-card-title>生成图片</ion-card-title>
+      <ion-card-subtitle>根据您填写的信息,我给你生成的图片。</ion-card-subtitle>
+    </ion-card-header>
+    <ion-list>
+      <ion-item>
+        <!-- 生成结果 -->
+        @if(shareData.images) {
+        @for(imageUrl of shareData.images;track imageUrl){
+        <img [src]="imageUrl" alt="" srcset="">
+        }
+        }
+      </ion-item>
+    </ion-list>
+  </ion-card>
+
+
 </ion-content>

+ 93 - 10
TFPower-app/src/app/page/taskchain-page/taskchain-page.component.ts

@@ -3,13 +3,18 @@ import {
   IonButton,
   IonCard,
   IonCardContent,
+  IonCardHeader,
+  IonCardSubtitle,
+  IonCardTitle,
   IonContent,
   IonHeader,
   IonIcon,
   IonItem,
+  IonList,
   IonProgressBar,
   IonTitle,
   IonToolbar,
+  ModalController,
 } from '@ionic/angular/standalone';
 import { AgentTaskStep } from 'src/app/agent/agent.task';
 import { addIcons } from 'ionicons';
@@ -18,6 +23,8 @@ import {
   ellipseOutline,
   reloadCircleOutline,
 } from 'ionicons/icons';
+import { AgentUserinputComponent } from 'src/app/agent/agent-userinput/agent-userinput.component';
+import { DalleOptions, FmodeChatCompletion, ImagineWork } from 'fmode-ng';
 addIcons({ ellipseOutline, checkmarkCircleOutline, reloadCircleOutline });
 
 @Component({
@@ -33,44 +40,120 @@ addIcons({ ellipseOutline, checkmarkCircleOutline, reloadCircleOutline });
     IonContent,
     IonItem,
     IonCard,
+    IonCardHeader,
+    IonCardTitle,
+    IonCardSubtitle,
     IonCardContent,
     IonProgressBar,
     IonIcon,
+    IonList,
   ],
 })
 export class TaskchainPageComponent {
-  constructor() {}
+  constructor(private modalCtrl: ModalController) {}
+  // constructor() {}
 
   taskList: AgentTaskStep[] = [];
   wait(duration: number = 1000) {
-    return new Promise((resolve, reject) => {
+    return new Promise((resolve) => {
       setInterval(() => {
         resolve(true);
       }, duration);
     });
   }
+
+  // 组件用户输入
+  async userInput(options: { fieldsArray: any }) {
+    const modal = await this.modalCtrl.create({
+      component: AgentUserinputComponent,
+      componentProps: {
+        fieldsArray: options.fieldsArray,
+      },
+    });
+    modal.present();
+    const { data, role } = await modal.onWillDismiss();
+    if (role === 'confirm') {
+      return data;
+    }
+  }
+
+  // 创建任务集
   shareData: any = {};
   createTask() {
+    // task1
     let task1 = new AgentTaskStep({
       title: 'AI扩展更多信息',
       shareData: this.shareData,
     });
-    task1.handle = async () => {
-      await this.wait(5000);
-      console.log('AI扩展更多信息,执行中...');
-      task1.progress = 1;
+    task1.handle = () => {
+      return new Promise(async (resolve) => {
+        // await this.wait(5000);
+        console.log('AI扩展更多信息,执行中...');
+        let userInput = await this.userInput({
+          fieldsArray: [
+            {
+              name: '绘图要求',
+              type: 'text',
+              placeholder: '主题+元素+风格',
+            },
+            {
+              name: '图片类型',
+              type: 'text',
+              placeholder: 'logo/普通图片/海报',
+            },
+          ],
+        });
+        console.log(userInput);
+        // console.log(userInput['图片类型']);
+
+        // ai生成更详细的内容
+        let PromptTemplate = `请您作为一名专业的美术大家,请根据以下需求给出更详细的补充,用最少的文字表达出来。需求有:${userInput['绘图要求']} + ${userInput['图片类型']}`;
+        console.log(PromptTemplate);
+
+        let completion = new FmodeChatCompletion([
+          { role: 'system', content: '' },
+          { role: 'user', content: PromptTemplate },
+        ]);
+
+        completion.sendCompletion().subscribe((message: any) => {
+          // 打印消息体
+          // console.log(message.content);
+          // 赋值消息内容给组件内属性
+          this.shareData.PictureDescResult = message.content;
+          if (message?.complete) {
+            task1.progress = 1;
+            resolve(true);
+          }
+        });
+      });
     };
 
+    // task2
     let task2 = new AgentTaskStep({
       title: 'AI生成图片',
       shareData: this.shareData,
     });
-    task2.handle = async () => {
-      await this.wait(3000);
-      console.log('AI生成图片,执行中...');
-      task2.progress = 1;
+    task2.handle = () => {
+      return new Promise(async (resolve) => {
+        // await this.wait(3000);
+        console.log('AI生成图片,执行中...');
+
+        let imagineWork = new ImagineWork();
+        let PicturePrompt = `${task1.shareData.PictureDescResult}风格,画面不带任何文字。`;
+        let options: DalleOptions = { prompt: PicturePrompt };
+        imagineWork?.draw(options).subscribe((work: any) => {
+          // console.log('imagineWork', work?.toJSON());
+          // console.log('images', work?.get('images'));
+          if (work?.get('images')?.length) {
+            this.shareData.images = work?.get('images');
+            task2.progress = 1;
+            resolve(true);
+          }
+        });
+      });
     };
 
+    //taskList
     this.taskList = [task1, task2];
     this.AngentExecutor(this.taskList);
   }

+ 4 - 1
TFPower-app/src/main.ts

@@ -13,6 +13,7 @@ import {
 import { routes } from './app/app.routes';
 import { AppComponent } from './app/app.component';
 
+// 添加
 // 引用HttpClient方法
 import { provideHttpClient } from '@angular/common/http';
 // 引用移动端授权检测供应器
@@ -25,14 +26,16 @@ localStorage.setItem(
   'NOVA_APIG_SERVER',
   'aHR0cHMlM0ElMkYlMkZzZXJ2ZXIuZm1vZGUuY24lMkZhcGklMkZhcGlnJTJG'
 );
-
 // let token = `r:E4KpGvTEto-187799890851732794669`;
 Parse.User.become('r:E4KpGvTEto-187799890851732794669');
+
 bootstrapApplication(AppComponent, {
   providers: [
     { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
     provideIonicAngular(),
     provideRouter(routes, withPreloading(PreloadAllModules)),
+
+    // 添加
     // 添加HttpClient供应器
     provideHttpClient(),
     // 添加Diagnostic