Browse Source

feat(aiChat): 添加选择题和问答题生成功能及API支持

- 新增getWorkPageId API用于获取工作页面ID
- 修改chat_no_stream和chat_stream函数参数为可选
- 新增chat_no_stream2函数用于处理JSON格式的AI响应
- 在aiChat.vue中添加生成选择题和问答题的逻辑
- 添加页面创建和iframe元素生成功能
lsc 2 weeks ago
parent
commit
9b0bfb0e09
3 changed files with 154 additions and 16 deletions
  1. 85 10
      src/components/CollapsibleToolbar/componets/aiChat.vue
  2. 5 2
      src/services/course.ts
  3. 64 4
      src/tools/aiChat.ts

+ 85 - 10
src/components/CollapsibleToolbar/componets/aiChat.vue

@@ -9,7 +9,7 @@
                 </div>
                 <div class="message-content ai-message chat" v-if="message.aiContent">
                     <div v-html="message.aiContent"></div>
-                    <button class="confirm-btn" v-if="message.jsonData?.isChoice">确定</button>
+                    <button class="confirm-btn" v-if="message.jsonData?.gType !== 'chat'" @click="generate(message)">确定</button>
                 </div>
             </div>
         </div>
@@ -50,10 +50,11 @@
 
 <script lang="ts" setup>
 import { ref, onMounted, useTemplateRef, nextTick } from 'vue'
-import { chat_no_stream, chat_stream, getAgentModel } from '@/tools/aiChat'
+import { chat_no_stream, chat_stream, getAgentModel, chat_no_stream2 } from '@/tools/aiChat'
 import { useSlidesStore } from '@/store'
 import { lang } from '@/main'
 import MarkdownIt from 'markdown-it'
+import { getWorkPageId } from '@/services/course'
 
 interface ChatMessage {
     uid?: string
@@ -76,7 +77,7 @@ interface ChatMessage {
         url?: string
     }>
     jsonData?: {
-        isChoice?: boolean
+        gType?: string
         headUrl?: string
         assistantName?: string
         sourceArray?: Array<{
@@ -154,12 +155,31 @@ const slidesStore = useSlidesStore()
 const gType = ref('chat')
 
 const sendAction = async (action: string) => {
-  const content = await chat_no_stream(action, agentid1.value, props.userid || '', lang.lang)
-  console.log(content)
-  // 渲染 Markdown 格式
   const md = new MarkdownIt()
-  const html = md.render(content)
-  messages.value.at(-1).aiContent = html
+  if (gType.value === 'chat') {
+    const content = await chat_no_stream(action, agentid1.value, props.userid || '', lang.lang)
+    console.log(content)
+    // 渲染 Markdown 格式
+    try {
+      gType.value = JSON.parse(content).intent
+    }
+    catch (error) {
+      gType.value = 'chat'
+    }
+
+    // generate_qa // generate_choice_question
+    if (gType.value !== 'chat') {
+      messages.value.at(-1).jsonData = {
+        gType: gType.value
+      }
+    }
+  }
+  else {
+    messages.value.at(-1).jsonData = {
+      gType: gType.value
+    }
+  }
+
 
 
   const prompt = `
@@ -178,11 +198,66 @@ const sendAction = async (action: string) => {
       chatLoading.value = false
       prevChatResult()
     }
-  }).catch(err => {
+  }, session_name.value).catch(err => {
     chatLoading.value = false
     console.log('err', err)
-  }, session_name.value)
+  })
 }
+import useCreateElement from '@/hooks/useCreateElement'
+import useSlideHandler from '@/hooks/useSlideHandler'
+const { createSlide } = useSlideHandler()
+const { createFrameElement } = useCreateElement()
+
+const generate = (message: ChatMessage) => {
+  if (message.jsonData?.gType === 'generate_choice_question') {
+    console.log(message.jsonData?.gType)
+    const prompt = [
+        {
+          role: 'user',
+          content: `这是用户输入的内容:“${message.aiContent}”,根据用户输入的内容,生成选择题的json。输出一个json格式的回复,格式如下:{"testCount":1,"testTitle":"","testJson":[{"id":"7de1fdb4-bec3-4324-8986-4623f838e3d7","type":"2","teststitle":"1+1?","checkList":["1","2","3"],"timuList":[],"answer":[1],"userAnswer":[],"explanation":"解析"}]}。输出语言为${lang.lang === "en"? "英文" : lang.lang === "hk"? "繁体中文" : "简体中文"}`,
+        },
+      ];
+      chat_no_stream2(prompt, { type: 'json_object' }).then(async (res: any) => {
+        console.log('选择题', JSON.parse(res));
+        gType.value = 'chat'
+        setPageId(45, res).then(res => {
+            let url = `https://beta.pbl.cocorobo.cn/pbl-teacher-table/dist/workPage.html#/setWorkPage?id=${res}&type=${45}`;
+            createSlide()
+            createFrameElement(url, 45)
+        });
+      });
+  }
+  else if (message.jsonData?.gType === 'generate_qa') {
+    console.log(message.jsonData?.gType)
+        const prompt = [
+        {
+          role: 'user',
+          content: `这是用户输入的内容:“${message.aiContent}”,根据用户输入的内容,生成问答题的json。输出一个json格式的回复,格式如下:{"answerQ":"问题","answer":"","fileList":[],"imageList":[],"evaluationCriteria":"评价标准"}。输出语言为${lang.lang === "en"? "英文" : lang.lang === "hk"? "繁体中文" : "简体中文"}`,
+        },
+      ];
+      chat_no_stream2(prompt, { type: 'json_object' }).then((res: any) => {
+        console.log('问答题', JSON.parse(res));
+        gType.value = 'chat'
+            setPageId(15, res).then(res => {
+            let url = `https://beta.pbl.cocorobo.cn/pbl-teacher-table/dist/workPage.html#/setWorkPage?id=${res}&type=${15}`;
+            createSlide()
+            createFrameElement(url, 15)
+        });
+      });
+  }
+}
+
+const setPageId = async (tool: any, json: any) => {
+    const res = await getWorkPageId({
+        userid: props.userid || '',
+        type: tool,
+        json: json
+    })
+    return res[0][0].id
+}
+
+
+
 const agentid1 = ref('cbb29b41-2a4a-4453-bf8d-357929ced4bd')// 判断意图
 const agentid2 = ref('f86aa63c-b7b7-4d03-9b37-b59f116d36f3')// 生成内容
 

+ 5 - 2
src/services/course.ts

@@ -194,7 +194,9 @@ export const getWorkDetail = (params: any): Promise<any> => {
 }
 
 
-
+export const getWorkPageId = (params: any): Promise<any> => {
+  return axios.post(`${API_URL}insert_workPage`, [params])
+}
 
 
 
@@ -216,6 +218,7 @@ export default {
   getChatList,
   getAgentData,
   clearDialogue,
-  getWorkDetail
+  getWorkDetail,
+  getWorkPageId
 }
 

+ 64 - 4
src/tools/aiChat.ts

@@ -33,7 +33,7 @@ const DEFAULT_PARAMS: Omit<ChatParams, 'message' | 'uid' | 'stream'> = {
   tts_language: 'zh-CN'
 }
 
-export const chat_no_stream = async (msg: string, agentId: string, userId: string, language: string, session_name: string = uuidv4()): Promise<string> => {
+export const chat_no_stream = async (msg: string, agentId: string, userId: string, language: string, session_name?: string): Promise<string> => {
   const agentData = await getAgentModel(agentId)
   const params: ChatParams = {
     ...DEFAULT_PARAMS,
@@ -44,7 +44,7 @@ export const chat_no_stream = async (msg: string, agentId: string, userId: strin
     model: agentData?.modelType || 'open-doubao',
     userId: userId,
     tts_language: getTtsLanguage(language),
-    session_name: session_name
+    session_name: session_name || uuidv4()
   }
 
   const res = await axios.post('https://appapi.cocorobo.cn/api/agentchats/ai_agent_chat', params)
@@ -77,7 +77,7 @@ export const chat_stream = async (
   userId: string,
   language: string,
   onMessage: (event: { type: 'message' | 'close' | 'error' | 'messageEnd'; data: string }) => void,
-  session_name: string = uuidv4()
+  session_name?: string
 ): Promise<void> => {
   const agentData = await getAgentModel(agentId)
   const params: ChatParams = {
@@ -89,7 +89,7 @@ export const chat_stream = async (
     model: agentData?.modelType || 'open-doubao',
     userId: userId,
     tts_language: getTtsLanguage(language),
-    session_name: session_name
+    session_name: session_name || uuidv4()
   }
 
   const ctrl = new AbortController()
@@ -158,3 +158,63 @@ export const getTtsLanguage = (langCode: string) => {
     default :return 'zh-CN'
   }
 }
+
+// AI 模型常量
+const AI_MODEL_CONSTANTS = {
+  DEFAULT_MODEL: 'gpt-4o-2024-11-20'
+}
+
+export const chat_no_stream2 = async (prompt: any[] = [], response_format = {
+  "type": "text"
+}, model = AI_MODEL_CONSTANTS.DEFAULT_MODEL) => {
+  return await new Promise((resolve) => {
+    let uid = uuidv4();
+    let data = JSON.stringify({
+      model: model,
+      temperature: 0,
+      max_tokens: 4096,
+      top_p: 1,
+      frequency_penalty: 0,
+      presence_penalty: 0,
+      messages: prompt,
+      uid: uid,
+      mind_map_question: '',
+      stream: false,
+      response_format: response_format
+    });
+    let config = {
+      method: 'post',
+      url: 'https://appapi.cocorobo.cn/api/common/chat',
+      headers: {
+        'Content-Type': 'application/json'
+      },
+      data: data,
+    };
+    axios(config)
+      .then((response) => {
+        let content = response?.FunctionResponse?.choices[0]?.message?.content || '';
+
+        // 清理可能的 markdown 格式
+        if (content.includes('```json')) {
+          // 提取 ```json 和 ``` 之间的内容
+          const jsonMatch = content.match(/```json\s*([\s\S]*?)\s*```/);
+          if (jsonMatch) {
+            content = jsonMatch[1].trim();
+          }
+        } else if (content.includes('```')) {
+          // 提取 ``` 和 ``` 之间的内容
+          const codeMatch = content.match(/```\s*([\s\S]*?)\s*```/);
+          if (codeMatch) {
+            content = codeMatch[1].trim();
+          }
+        }
+
+        resolve(content);
+      })
+      .catch( (error)=> {
+        console.log(error);
+        // this.$message.error('服务器繁忙');
+        resolve(false);
+      });
+  });
+}