|
@@ -221,6 +221,8 @@ import FileInput from '@/components/FileInput2.vue'
|
|
|
import axios from '@/services/config'
|
|
import axios from '@/services/config'
|
|
|
import message from '@/utils/message'
|
|
import message from '@/utils/message'
|
|
|
import AiWeb from './aiWeb.vue'
|
|
import AiWeb from './aiWeb.vue'
|
|
|
|
|
+import katex from 'katex'
|
|
|
|
|
+import 'katex/dist/katex.min.css'
|
|
|
|
|
|
|
|
interface ChatMessage {
|
|
interface ChatMessage {
|
|
|
uid?: string
|
|
uid?: string
|
|
@@ -451,7 +453,8 @@ const loadingDots = ref('...')
|
|
|
const loadingInterval = ref(null)
|
|
const loadingInterval = ref(null)
|
|
|
|
|
|
|
|
const sendAction = async (action: string) => {
|
|
const sendAction = async (action: string) => {
|
|
|
- const md = new MarkdownIt()
|
|
|
|
|
|
|
+ // html: true 保留 katexZ 生成的公式HTML,使其能正常渲染到页面
|
|
|
|
|
+ const md = new MarkdownIt({ html: true })
|
|
|
if (gType.value === 'chat' || gType.value === 'generate_interactive_web' || gType.value === 'trigger_tool_recommend' || gType.value === 'trigger_batch_tool') {
|
|
if (gType.value === 'chat' || gType.value === 'generate_interactive_web' || gType.value === 'trigger_tool_recommend' || gType.value === 'trigger_batch_tool') {
|
|
|
const result = chat_no_stream(action, agentid1.value, props.userid || '', lang.lang)
|
|
const result = chat_no_stream(action, agentid1.value, props.userid || '', lang.lang)
|
|
|
noStreamController.value = result
|
|
noStreamController.value = result
|
|
@@ -744,13 +747,13 @@ const sendAction = async (action: string) => {
|
|
|
|
|
|
|
|
chat_stream(prompt, agentid, props.userid || '', lang.lang, (event) => {
|
|
chat_stream(prompt, agentid, props.userid || '', lang.lang, (event) => {
|
|
|
if (event.type === 'message') {
|
|
if (event.type === 'message') {
|
|
|
- messages.value.at(-1).aiContent = md.render(event.data)
|
|
|
|
|
|
|
+ messages.value.at(-1).aiContent = md.render(katexZ(event.data))
|
|
|
|
|
|
|
|
messages.value.at(-1).loading = false
|
|
messages.value.at(-1).loading = false
|
|
|
prevChatResult()
|
|
prevChatResult()
|
|
|
}
|
|
}
|
|
|
else if (event.type === 'messageEnd') {
|
|
else if (event.type === 'messageEnd') {
|
|
|
- messages.value.at(-1).aiContent = md.render(event.data)
|
|
|
|
|
|
|
+ messages.value.at(-1).aiContent = md.render(katexZ(event.data))
|
|
|
messages.value.at(-1).chatloading = false
|
|
messages.value.at(-1).chatloading = false
|
|
|
chatLoading.value = false
|
|
chatLoading.value = false
|
|
|
prevChatResult()
|
|
prevChatResult()
|
|
@@ -768,6 +771,47 @@ import useSlideHandler from '@/hooks/useSlideHandler'
|
|
|
const { createSlide } = useSlideHandler()
|
|
const { createSlide } = useSlideHandler()
|
|
|
const { createFrameElement } = useCreateElement()
|
|
const { createFrameElement } = useCreateElement()
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+const katexZ = (str) => {
|
|
|
|
|
+ if (!str) return ''
|
|
|
|
|
+ const escapeHtml = (text) => {
|
|
|
|
|
+ return text
|
|
|
|
|
+ .replace(/&/g, '&')
|
|
|
|
|
+ .replace(/</g, '<')
|
|
|
|
|
+ .replace(/>/g, '>')
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ let result = ''
|
|
|
|
|
+ let lastIndex = 0
|
|
|
|
|
+ // 匹配 $$...$$(块级公式)或 $...$(行内公式)
|
|
|
|
|
+ const regex = /\$\$([\s\S]+?)\$\$|\$([^$]+?)\$/g
|
|
|
|
|
+ let match
|
|
|
|
|
+ while ((match = regex.exec(str)) !== null) {
|
|
|
|
|
+ // 转义并拼接公式前的纯文本
|
|
|
|
|
+ result += escapeHtml(str.substring(lastIndex, match.index))
|
|
|
|
|
+ if (match[1] !== undefined) {
|
|
|
|
|
+ // 块级公式
|
|
|
|
|
+ result += katex.renderToString(match[1], {
|
|
|
|
|
+ throwOnError: false,
|
|
|
|
|
+ displayMode: true
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ // 行内公式
|
|
|
|
|
+ result += katex.renderToString(match[2], {
|
|
|
|
|
+ throwOnError: false
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ lastIndex = regex.lastIndex
|
|
|
|
|
+ }
|
|
|
|
|
+ // 拼接剩余纯文本
|
|
|
|
|
+ result += escapeHtml(str.substring(lastIndex))
|
|
|
|
|
+ return result || escapeHtml(str)
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (e) {
|
|
|
|
|
+ return str
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
const setUrl = () => {
|
|
const setUrl = () => {
|
|
|
let url = 'https://beta.pbl.cocorobo.cn'
|
|
let url = 'https://beta.pbl.cocorobo.cn'
|
|
|
if (lang.lang === 'cn') {
|
|
if (lang.lang === 'cn') {
|
|
@@ -792,7 +836,7 @@ const generate = (message: ChatMessage) => {
|
|
|
const prompt = [
|
|
const prompt = [
|
|
|
{
|
|
{
|
|
|
role: 'user',
|
|
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' ? '繁体中文' : '简体中文'}
|
|
|
|
|
|
|
+ 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) => {
|
|
chat_no_stream2(prompt, { type: 'json_object' }).then(async (res: any) => {
|
|
@@ -1007,7 +1051,7 @@ const createTool = async (array: any[], tool: any, index: number, slide: any) =>
|
|
|
|
|
|
|
|
const res = await chat_no_stream2([{
|
|
const res = await chat_no_stream2([{
|
|
|
role: 'user',
|
|
role: 'user',
|
|
|
- content: `这是用户输入的内容:"${content}",根据用户输入的内容,生成json。输出一个json格式的回复,格式如下:${jsonFormat}。`,
|
|
|
|
|
|
|
+ content: `这是用户输入的内容:"${content}",根据用户输入的内容,有数学公式的话要保留对应的符号比如$,生成json。输出一个json格式的回复,格式如下:${jsonFormat}。`,
|
|
|
}], { type: 'json_object' })
|
|
}], { type: 'json_object' })
|
|
|
|
|
|
|
|
console.log(`${tool.tool_name}`, res)
|
|
console.log(`${tool.tool_name}`, res)
|