mirror of
https://github.com/jihe520/MathModelAgent.git
synced 2026-09-19 08:09:48 +08:00
fix bug: tool_calls match tool response
fix bug: tool_calls match tool response modify: the method of memory manage add : timer
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from app.core.llm.llm import LLM
|
||||
from app.core.llm.llm import LLM, simple_chat
|
||||
from app.utils.log_util import logger
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ class Agent:
|
||||
self.current_chat_turns = 0 # 重置对话轮次计数器
|
||||
|
||||
# 更新对话历史
|
||||
self.append_chat_history({"role": "system", "content": system_prompt})
|
||||
self.append_chat_history({"role": "user", "content": prompt})
|
||||
await self.append_chat_history({"role": "system", "content": system_prompt})
|
||||
await self.append_chat_history({"role": "user", "content": prompt})
|
||||
|
||||
# 获取历史消息用于本次对话
|
||||
response = await self.model.chat(
|
||||
@@ -50,14 +50,80 @@ class Agent:
|
||||
logger.error(f"Agent执行失败: {str(e)}")
|
||||
return error_msg
|
||||
|
||||
def append_chat_history(self, msg: dict) -> None:
|
||||
self.clear_memory()
|
||||
async def append_chat_history(self, msg: dict) -> None:
|
||||
await self.clear_memory()
|
||||
self.chat_history.append(msg)
|
||||
|
||||
def clear_memory(self):
|
||||
async def clear_memory(self):
|
||||
"""当聊天历史超过最大记忆轮次时,使用 simple_chat 进行总结压缩"""
|
||||
if len(self.chat_history) <= self.max_memory:
|
||||
return
|
||||
logger.info(f"{self.__class__.__name__}:清除记忆")
|
||||
|
||||
# 使用切片保留第一条和最后两条消息
|
||||
self.chat_history = self.chat_history[:2] + self.chat_history[-5:]
|
||||
logger.info(
|
||||
f"{self.__class__.__name__}:开始清除记忆,当前记录数:{len(self.chat_history)}"
|
||||
)
|
||||
|
||||
try:
|
||||
# 保留第一条系统消息
|
||||
system_msg = (
|
||||
self.chat_history[0]
|
||||
if self.chat_history and self.chat_history[0]["role"] == "system"
|
||||
else None
|
||||
)
|
||||
|
||||
# 构造总结提示
|
||||
summarize_history = []
|
||||
if system_msg:
|
||||
summarize_history.append(system_msg)
|
||||
|
||||
# 添加要总结的对话内容(跳过第一条系统消息和最后5条消息)
|
||||
start_idx = 1 if system_msg else 0
|
||||
end_idx = len(self.chat_history) - 5
|
||||
|
||||
if end_idx > start_idx:
|
||||
summarize_history.append(
|
||||
{
|
||||
"role": "user",
|
||||
"content": f"请简洁总结以下对话的关键内容和重要结论,保留重要的上下文信息:\n\n{self._format_history_for_summary(self.chat_history[start_idx:end_idx])}",
|
||||
}
|
||||
)
|
||||
|
||||
# 调用 simple_chat 进行总结
|
||||
summary = await simple_chat(self.model, summarize_history)
|
||||
|
||||
# 重构聊天历史:系统消息 + 总结 + 最后5条消息
|
||||
new_history = []
|
||||
if system_msg:
|
||||
new_history.append(system_msg)
|
||||
|
||||
new_history.append(
|
||||
{"role": "assistant", "content": f"[历史对话总结] {summary}"}
|
||||
)
|
||||
|
||||
# 添加最后5条消息
|
||||
new_history.extend(self.chat_history[-5:])
|
||||
|
||||
self.chat_history = new_history
|
||||
logger.info(
|
||||
f"{self.__class__.__name__}:记忆清除完成,压缩至:{len(self.chat_history)}条记录"
|
||||
)
|
||||
else:
|
||||
logger.info(f"{self.__class__.__name__}:无需清除记忆,记录数量合理")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"记忆清除失败,使用简单切片策略: {str(e)}")
|
||||
# 如果总结失败,回退到简单的切片策略
|
||||
self.chat_history = self.chat_history[:2] + self.chat_history[-5:]
|
||||
|
||||
def _format_history_for_summary(self, history: list[dict]) -> str:
|
||||
"""格式化历史记录用于总结"""
|
||||
formatted = []
|
||||
for msg in history:
|
||||
role = msg["role"]
|
||||
content = (
|
||||
msg["content"][:500] + "..."
|
||||
if len(msg["content"]) > 500
|
||||
else msg["content"]
|
||||
) # 限制长度
|
||||
formatted.append(f"{role}: {content}")
|
||||
return "\n".join(formatted)
|
||||
|
||||
@@ -40,9 +40,11 @@ class CoderAgent(Agent): # 同样继承自Agent类
|
||||
if self.is_first_run:
|
||||
logger.info("首次运行,添加系统提示和数据集文件信息")
|
||||
self.is_first_run = False
|
||||
self.append_chat_history({"role": "system", "content": self.system_prompt})
|
||||
await self.append_chat_history(
|
||||
{"role": "system", "content": self.system_prompt}
|
||||
)
|
||||
# 当前数据集文件
|
||||
self.append_chat_history(
|
||||
await self.append_chat_history(
|
||||
{
|
||||
"role": "user",
|
||||
"content": f"当前文件夹下的数据集文件{get_current_files(self.work_dir, 'data')}",
|
||||
@@ -51,7 +53,7 @@ class CoderAgent(Agent): # 同样继承自Agent类
|
||||
|
||||
# 添加 sub_task
|
||||
logger.info(f"添加子任务提示: {prompt}")
|
||||
self.append_chat_history({"role": "user", "content": prompt})
|
||||
await self.append_chat_history({"role": "user", "content": prompt})
|
||||
|
||||
retry_count = 0
|
||||
last_error_message = ""
|
||||
@@ -118,7 +120,9 @@ class CoderAgent(Agent): # 同样继承自Agent类
|
||||
)
|
||||
|
||||
# 更新对话历史 - 添加助手的响应
|
||||
self.append_chat_history(response.choices[0].message.model_dump())
|
||||
await self.append_chat_history(
|
||||
response.choices[0].message.model_dump()
|
||||
)
|
||||
logger.info(response.choices[0].message.model_dump())
|
||||
|
||||
# 执行工具调用
|
||||
@@ -132,7 +136,7 @@ class CoderAgent(Agent): # 同样继承自Agent类
|
||||
# 添加工具执行结果
|
||||
if error_occurred:
|
||||
# 即使发生错误也要添加tool响应
|
||||
self.append_chat_history(
|
||||
await self.append_chat_history(
|
||||
{
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_id,
|
||||
@@ -152,14 +156,14 @@ class CoderAgent(Agent): # 同样继承自Agent类
|
||||
SystemMessage(content="代码手反思纠正错误", type="error"),
|
||||
)
|
||||
|
||||
self.append_chat_history(
|
||||
await self.append_chat_history(
|
||||
{"role": "user", "content": reflection_prompt}
|
||||
)
|
||||
# 如果代码出错,返回重新开始
|
||||
continue
|
||||
else:
|
||||
# 成功执行的tool响应
|
||||
self.append_chat_history(
|
||||
await self.append_chat_history(
|
||||
{
|
||||
"role": "tool",
|
||||
"tool_call_id": tool_id,
|
||||
|
||||
@@ -19,8 +19,10 @@ class CoordinatorAgent(Agent):
|
||||
|
||||
async def run(self, ques_all: str) -> CoordinatorToModeler:
|
||||
"""用户输入问题 使用LLM 格式化 questions"""
|
||||
self.append_chat_history({"role": "system", "content": self.system_prompt})
|
||||
self.append_chat_history({"role": "user", "content": ques_all})
|
||||
await self.append_chat_history(
|
||||
{"role": "system", "content": self.system_prompt}
|
||||
)
|
||||
await self.append_chat_history({"role": "user", "content": ques_all})
|
||||
|
||||
response = await self.model.chat(
|
||||
history=self.chat_history,
|
||||
|
||||
@@ -18,8 +18,10 @@ class ModelerAgent(Agent): # 继承自Agent类
|
||||
self.system_prompt = MODELER_PROMPT
|
||||
|
||||
async def run(self, coordinator_to_modeler: CoordinatorToModeler) -> ModelerToCoder:
|
||||
self.append_chat_history({"role": "system", "content": self.system_prompt})
|
||||
self.append_chat_history(
|
||||
await self.append_chat_history(
|
||||
{"role": "system", "content": self.system_prompt}
|
||||
)
|
||||
await self.append_chat_history(
|
||||
{
|
||||
"role": "user",
|
||||
"content": json.dumps(coordinator_to_modeler.questions),
|
||||
|
||||
@@ -52,7 +52,9 @@ class WriterAgent(Agent): # 同样继承自Agent类
|
||||
|
||||
if self.is_first_run:
|
||||
self.is_first_run = False
|
||||
self.append_chat_history({"role": "system", "content": self.system_prompt})
|
||||
await self.append_chat_history(
|
||||
{"role": "system", "content": self.system_prompt}
|
||||
)
|
||||
|
||||
if available_images:
|
||||
self.available_images = available_images
|
||||
@@ -65,7 +67,7 @@ class WriterAgent(Agent): # 同样继承自Agent类
|
||||
logger.info(f"{self.__class__.__name__}:开始:执行对话")
|
||||
self.current_chat_turns += 1 # 重置对话轮次计数器
|
||||
|
||||
self.append_chat_history({"role": "user", "content": prompt})
|
||||
await self.append_chat_history({"role": "user", "content": prompt})
|
||||
|
||||
# 获取历史消息用于本次对话
|
||||
response = await self.model.chat(
|
||||
@@ -102,7 +104,7 @@ class WriterAgent(Agent): # 同样继承自Agent类
|
||||
)
|
||||
|
||||
# 更新对话历史 - 添加助手的响应
|
||||
self.append_chat_history(response.choices[0].message.model_dump())
|
||||
await self.append_chat_history(response.choices[0].message.model_dump())
|
||||
ic(response.choices[0].message.model_dump())
|
||||
|
||||
try:
|
||||
@@ -116,7 +118,7 @@ class WriterAgent(Agent): # 同样继承自Agent类
|
||||
# TODO: pass to frontend
|
||||
papers_str = self.scholar.papers_to_str(papers)
|
||||
logger.info(f"搜索文献结果\n{papers_str}")
|
||||
self.append_chat_history(
|
||||
await self.append_chat_history(
|
||||
{
|
||||
"role": "tool",
|
||||
"content": papers_str,
|
||||
@@ -143,14 +145,14 @@ class WriterAgent(Agent): # 同样继承自Agent类
|
||||
总结对话内容
|
||||
"""
|
||||
try:
|
||||
self.append_chat_history(
|
||||
await self.append_chat_history(
|
||||
{"role": "user", "content": "请简单总结以上完成什么任务取得什么结果:"}
|
||||
)
|
||||
# 获取历史消息用于本次对话
|
||||
response = await self.model.chat(
|
||||
history=self.chat_history, agent_name=self.__class__.__name__
|
||||
)
|
||||
self.append_chat_history(
|
||||
await self.append_chat_history(
|
||||
{"role": "assistant", "content": response.choices[0].message.content}
|
||||
)
|
||||
return response.choices[0].message.content
|
||||
|
||||
@@ -10,10 +10,6 @@ import {
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from '@/components/ui/tabs'
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
} from '@/components/ui/card'
|
||||
import CoderEditor from '@/components/AgentEditor/CoderEditor.vue'
|
||||
import WriterEditor from '@/components/AgentEditor/WriterEditor.vue'
|
||||
import ModelerEditor from '@/components/AgentEditor/ModelerEditor.vue'
|
||||
@@ -33,12 +29,44 @@ const taskStore = useTaskStore()
|
||||
|
||||
const writerSequence = ref<string[]>([]);
|
||||
|
||||
// 项目运行时长相关
|
||||
const startTime = ref<number>(Date.now())
|
||||
const currentTime = ref<number>(Date.now())
|
||||
let timer: ReturnType<typeof setInterval> | null = null
|
||||
|
||||
// 格式化运行时长
|
||||
const formatDuration = (ms: number): string => {
|
||||
const seconds = Math.floor(ms / 1000)
|
||||
const hours = Math.floor(seconds / 3600)
|
||||
const minutes = Math.floor((seconds % 3600) / 60)
|
||||
const remainingSeconds = seconds % 60
|
||||
|
||||
if (hours > 0) {
|
||||
return `${hours}h ${minutes}m ${remainingSeconds}s`
|
||||
} else if (minutes > 0) {
|
||||
return `${minutes}m ${remainingSeconds}s`
|
||||
} else {
|
||||
return `${remainingSeconds}s`
|
||||
}
|
||||
}
|
||||
|
||||
// 计算运行时长
|
||||
const runningDuration = ref<string>('0s')
|
||||
const updateDuration = () => {
|
||||
currentTime.value = Date.now()
|
||||
runningDuration.value = formatDuration(currentTime.value - startTime.value)
|
||||
}
|
||||
|
||||
console.log('Task ID:', props.task_id)
|
||||
|
||||
onMounted(async () => {
|
||||
taskStore.connectWebSocket(props.task_id)
|
||||
const res = await getWriterSeque();
|
||||
writerSequence.value = Array.isArray(res.data) ? res.data : [];
|
||||
|
||||
// 开始计时
|
||||
timer = setInterval(updateDuration, 1000)
|
||||
updateDuration() // 立即更新一次
|
||||
})
|
||||
|
||||
const openFolder = async () => {
|
||||
@@ -53,6 +81,11 @@ const openFolder = async () => {
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
taskStore.closeWebSocket()
|
||||
// 清理计时器
|
||||
if (timer) {
|
||||
clearInterval(timer)
|
||||
timer = null
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
@@ -66,19 +99,25 @@ onBeforeUnmount(() => {
|
||||
<ResizableHandle />
|
||||
<ResizablePanel :default-size="60" class="h-full min-w-0">
|
||||
<div class="flex h-full flex-col min-w-0">
|
||||
<Tabs default-value="coder" class="w-full h-full flex flex-col">
|
||||
<Tabs default-value="modeler" class="w-full h-full flex flex-col">
|
||||
<!-- TODO: Agent 的状态 -->
|
||||
<div class="border-b px-4 py-1 flex justify-between">
|
||||
<TabsList class="">
|
||||
<TabsTrigger value="modeler" class="text-sm">
|
||||
ModelerAgent
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="coder" class="text-sm">
|
||||
CoderAgent
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="writer" class="text-sm">
|
||||
WriterAgent
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="text-sm text-gray-600">
|
||||
运行时长: <span class="font-mono text-blue-600">{{ runningDuration }}</span>
|
||||
</div>
|
||||
<TabsList>
|
||||
<TabsTrigger value="modeler" class="text-sm">
|
||||
ModelerAgent
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="coder" class="text-sm">
|
||||
CoderAgent
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="writer" class="text-sm">
|
||||
WriterAgent
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</div>
|
||||
<!-- TODO: 其他选项 -->
|
||||
|
||||
<div class="flex justify-end gap-2">
|
||||
|
||||
Reference in New Issue
Block a user