This commit is contained in:
Sanjin
2025-05-24 14:24:38 +08:00
parent f7db538240
commit 31007b9713
5 changed files with 237 additions and 14 deletions
+6 -1
View File
@@ -106,5 +106,10 @@ class WriterMessage(AgentMessage):
# 所有可能的消息类型
MessageType = Union[
SystemMessage, UserMessage, ModelerMessage, CoderMessage, WriterMessage
SystemMessage,
UserMessage,
ModelerMessage,
CoderMessage,
WriterMessage,
CoordinatorMessage,
]
@@ -1,9 +1,180 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useTaskStore } from '@/stores/task'
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'
import { Separator } from '@/components/ui/separator'
const taskStore = useTaskStore()
// 获取最新的CoordinatorMessage
const latestCoordinatorMessage = computed(() => {
const messages = taskStore.coordinatorMessages
return messages.length > 0 ? messages[messages.length - 1] : null
})
// 解析CoordinatorMessage的JSON内容
const coordinatorData = computed(() => {
if (!latestCoordinatorMessage.value?.content) return null
try {
const content = latestCoordinatorMessage.value.content
// 移除可能的```json标记
const cleanContent = content.replace(/```json\n?/, '').replace(/```$/, '').trim()
return JSON.parse(cleanContent)
} catch (error) {
console.error('解析CoordinatorMessage失败:', error)
return null
}
})
// 获取最新的ModelerMessage
const latestModelerMessage = computed(() => {
const messages = taskStore.modelerMessages
return messages.length > 0 ? messages[messages.length - 1] : null
})
// 解析ModelerMessage的JSON内容
const modelerData = computed(() => {
if (!latestModelerMessage.value?.content) return null
try {
const content = latestModelerMessage.value.content
// 移除可能的```json标记
const cleanContent = content.replace(/```json\n?/, '').replace(/```$/, '').trim()
return JSON.parse(cleanContent)
} catch (error) {
console.error('解析ModelerMessage失败:', error)
return null
}
})
// 生成问题列表
const questionsList = computed(() => {
if (!coordinatorData.value) return []
const questions = []
for (let i = 1; i <= coordinatorData.value.ques_count; i++) {
const quesKey = `ques${i}`
if (coordinatorData.value[quesKey]) {
questions.push({
number: i,
content: coordinatorData.value[quesKey]
})
}
}
return questions
})
</script>
<template>
<div class="h-full min-w-0 pb-4">
modeler editor
<div class="h-full min-w-0 flex flex-col">
<!-- 上半部分CoordinatorMessage 结构化信息 -->
<div class="flex-1 p-4 overflow-auto">
<Card class="h-full">
<CardHeader>
<CardTitle class="text-lg font-semibold">题目信息</CardTitle>
</CardHeader>
<CardContent class="space-y-4">
<div v-if="coordinatorData">
<!-- 题目标题 -->
<div class="space-y-2">
<h3 class="text-base font-medium text-gray-700">题目标题</h3>
<div class="text-lg font-semibold text-gray-900">
{{ coordinatorData.title }}
</div>
</div>
<Separator />
<!-- 题目背景 -->
<div class="space-y-2">
<h3 class="text-base font-medium text-gray-700">题目背景</h3>
<div class="text-sm text-gray-800 leading-relaxed whitespace-pre-wrap">
{{ coordinatorData.background }}
</div>
</div>
<Separator />
<!-- 问题数量和问题列表 -->
<div class="space-y-2">
<div class="flex items-center gap-2">
<h3 class="text-base font-medium text-gray-700">问题列表</h3>
<span class="px-2 py-1 text-xs bg-gray-100 rounded">{{ coordinatorData.ques_count }} 个问题</span>
</div>
<div class="space-y-3">
<div v-for="question in questionsList" :key="question.number"
class="border-l-4 border-blue-500 pl-4 py-2 bg-blue-50 rounded-r">
<div class="text-sm font-medium text-blue-700 mb-1">
问题 {{ question.number }}
</div>
<div class="text-sm text-gray-800 leading-relaxed">
{{ question.content }}
</div>
</div>
</div>
</div>
</div>
<div v-else class="text-center py-8 text-gray-500">
暂无题目信息
</div>
</CardContent>
</Card>
</div>
<!-- 下半部分ModelerMessage 建模手册 -->
<div class="flex-1 p-4 pt-0 overflow-auto">
<Card class="h-full">
<CardHeader>
<CardTitle class="text-lg font-semibold">建模手册</CardTitle>
</CardHeader>
<CardContent>
<div v-if="modelerData" class="space-y-4">
<!-- EDA部分 -->
<div v-if="modelerData.eda" class="space-y-2">
<h3 class="text-base font-medium text-gray-700 flex items-center gap-2">
<span class="px-2 py-1 text-xs bg-gray-200 border rounded">EDA</span>
探索性数据分析
</h3>
<div class="text-sm text-gray-800 leading-relaxed whitespace-pre-wrap bg-gray-50 p-3 rounded">
{{ modelerData.eda }}
</div>
</div>
<!-- 问题解决方案 -->
<div v-for="question in questionsList" :key="`solution-${question.number}`" class="space-y-2">
<div v-if="modelerData[`ques${question.number}`]">
<h3 class="text-base font-medium text-gray-700 flex items-center gap-2">
<span class="px-2 py-1 text-xs bg-gray-200 border rounded">问题{{ question.number }}</span>
解决方案
</h3>
<div
class="text-sm text-gray-800 leading-relaxed whitespace-pre-wrap bg-green-50 p-3 rounded border-l-4 border-green-500">
{{ modelerData[`ques${question.number}`] }}
</div>
</div>
</div>
<!-- 敏感性分析 -->
<div v-if="modelerData.sensitivity_analysis" class="space-y-2">
<h3 class="text-base font-medium text-gray-700 flex items-center gap-2">
<span class="px-2 py-1 text-xs bg-gray-200 border rounded">敏感性分析</span>
</h3>
<div
class="text-sm text-gray-800 leading-relaxed whitespace-pre-wrap bg-orange-50 p-3 rounded border-l-4 border-orange-500">
{{ modelerData.sensitivity_analysis }}
</div>
</div>
</div>
<div v-else class="text-center py-8 text-gray-500">
暂无建模手册信息
</div>
</CardContent>
</Card>
</div>
</div>
</template>
+4
View File
@@ -16,6 +16,9 @@ import { submitModelingTask } from '@/apis/submitModelingApi'
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { Rocket } from 'lucide-vue-next'
import { useRouter } from 'vue-router'
import { useTaskStore } from '@/stores/task'
const taskStore = useTaskStore()
const currentStep = ref(1)
const fileUploaded = ref(true)
@@ -102,6 +105,7 @@ const handleSubmit = async () => {
)
taskId.value = response?.data?.task_id ?? null
taskStore.addUserMessage(question.value)
showSubmitSuccess.value = true
setTimeout(() => {
+38 -8
View File
@@ -1,9 +1,10 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { TaskWebSocket } from '@/utils/websocket'
import type { Message, CoderMessage, WriterMessage } from '@/utils/response'
import type { Message, CoderMessage, WriterMessage, UserMessage, ModelerMessage, CoordinatorMessage } from '@/utils/response'
// import messageData from '@/test/20250524-115938-d4c84576.json'
import messageData from '@/test/20250524-133152-0f9d6be8.json'
import { AgentType } from '@/utils/enum'
export const useTaskStore = defineStore('task', () => {
// 初始化时直接加载测试数据,确保页面首次渲染时有数据
@@ -30,6 +31,14 @@ export const useTaskStore = defineStore('task', () => {
ws?.close()
}
function addUserMessage(content: string) {
messages.value.push({
id: Date.now().toString(),
msg_type: 'user',
content: content,
} as UserMessage)
}
// 下载消息
function downloadMessages() {
const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(messages.value, null, 2))
@@ -45,10 +54,10 @@ export const useTaskStore = defineStore('task', () => {
const chatMessages = computed(() =>
messages.value.filter(
(msg) => {
if (msg.msg_type === 'agent' && msg.agent_type === 'CoderAgent' && msg.content == null) {
if (msg.msg_type === 'agent' && msg.agent_type === AgentType.CODER && msg.content == null) {
return false
}
if (msg.msg_type === 'agent' && msg.agent_type === 'WriterAgent') {
if (msg.msg_type === 'agent' && msg.agent_type === AgentType.WRITER) {
return false
}
return msg.msg_type === 'agent' && msg.content || msg.msg_type === 'system'
@@ -56,12 +65,30 @@ export const useTaskStore = defineStore('task', () => {
)
)
const coordinatorMessages = computed(() =>
messages.value.filter(
(msg): msg is CoordinatorMessage =>
msg.msg_type === 'agent' &&
msg.agent_type === AgentType.COORDINATOR &&
msg.content != null
)
)
const modelerMessages = computed(() =>
messages.value.filter(
(msg): msg is ModelerMessage =>
msg.msg_type === 'agent' &&
msg.agent_type === AgentType.MODELER &&
msg.content != null
)
)
const coderMessages = computed(() =>
messages.value.filter(
(msg): msg is CoderMessage =>
msg.msg_type === 'agent' &&
msg.agent_type === 'CoderAgent' &&
(msg.code != null || msg.code_results != null)
msg.agent_type === AgentType.CODER &&
msg.content != null
)
)
@@ -69,7 +96,7 @@ export const useTaskStore = defineStore('task', () => {
messages.value.filter(
(msg): msg is WriterMessage =>
msg.msg_type === 'agent' &&
msg.agent_type === 'WriterAgent' &&
msg.agent_type === AgentType.WRITER &&
msg.content != null
)
)
@@ -79,7 +106,7 @@ export const useTaskStore = defineStore('task', () => {
// 反向遍历消息找到最新的文件列表
for (let i = coderMessages.value.length - 1; i >= 0; i--) {
const msg = coderMessages.value[i]
if ('files' in msg && msg.files?.length) {
if ('files' in msg && msg.files && Array.isArray(msg.files) && msg.files.length > 0) {
console.log('找到文件列表:', msg.files)
return msg.files
}
@@ -96,11 +123,14 @@ export const useTaskStore = defineStore('task', () => {
return {
messages,
chatMessages,
coordinatorMessages,
modelerMessages,
coderMessages,
writerMessages,
files,
connectWebSocket,
closeWebSocket,
downloadMessages
downloadMessages,
addUserMessage
}
})
+16 -3
View File
@@ -15,7 +15,7 @@ export interface ToolMessage extends BaseMessage {
msg_type: 'tool';
tool_name: 'execute_code' | 'search_scholar';
input: {};
output: [];
output: string[] | OutputItem[];
}
export interface SystemMessage extends BaseMessage {
@@ -79,7 +79,20 @@ export interface ErrorExecution extends BaseCodeExecution {
traceback: string;
}
export type CodeExecutionResult = StdOutExecution | StdErrExecution | ResultExecution | ErrorExecution;
export type OutputItem = StdOutExecution | StdErrExecution | ResultExecution | ErrorExecution;
export interface ScholarMessage extends ToolMessage {
tool_name: 'search_scholar';
input: {};
output: string[];
}
export interface InterpreterMessage extends ToolMessage {
tool_name: 'execute_code';
input: {};
output: OutputItem[];
}
export interface CoderMessage extends AgentMessage {
agent_type: AgentType.CODER;
@@ -90,4 +103,4 @@ export interface WriterMessage extends AgentMessage {
sub_title?: string;
}
export type Message = SystemMessage | UserMessage | CoderMessage | WriterMessage;
export type Message = SystemMessage | UserMessage | CoderMessage | WriterMessage | ModelerMessage | CoordinatorMessage;