Skip to content

Commit 25dfb50

Browse files
committed
fix bug: tool_calls match tool response
fix bug: tool_calls match tool response modify: the method of memory manage add : timer
1 parent 5fef399 commit 25dfb50

File tree

6 files changed

+157
-42
lines changed

6 files changed

+157
-42
lines changed

backend/app/core/agents/agent.py

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from app.core.llm.llm import LLM
1+
from app.core.llm.llm import LLM, simple_chat
22
from app.utils.log_util import logger
33

44

@@ -32,8 +32,8 @@ async def run(self, prompt: str, system_prompt: str, sub_title: str) -> str:
3232
self.current_chat_turns = 0 # 重置对话轮次计数器
3333

3434
# 更新对话历史
35-
self.append_chat_history({"role": "system", "content": system_prompt})
36-
self.append_chat_history({"role": "user", "content": prompt})
35+
await self.append_chat_history({"role": "system", "content": system_prompt})
36+
await self.append_chat_history({"role": "user", "content": prompt})
3737

3838
# 获取历史消息用于本次对话
3939
response = await self.model.chat(
@@ -50,14 +50,80 @@ async def run(self, prompt: str, system_prompt: str, sub_title: str) -> str:
5050
logger.error(f"Agent执行失败: {str(e)}")
5151
return error_msg
5252

53-
def append_chat_history(self, msg: dict) -> None:
54-
self.clear_memory()
53+
async def append_chat_history(self, msg: dict) -> None:
54+
await self.clear_memory()
5555
self.chat_history.append(msg)
5656

57-
def clear_memory(self):
57+
async def clear_memory(self):
58+
"""当聊天历史超过最大记忆轮次时,使用 simple_chat 进行总结压缩"""
5859
if len(self.chat_history) <= self.max_memory:
5960
return
60-
logger.info(f"{self.__class__.__name__}:清除记忆")
6161

62-
# 使用切片保留第一条和最后两条消息
63-
self.chat_history = self.chat_history[:2] + self.chat_history[-5:]
62+
logger.info(
63+
f"{self.__class__.__name__}:开始清除记忆,当前记录数:{len(self.chat_history)}"
64+
)
65+
66+
try:
67+
# 保留第一条系统消息
68+
system_msg = (
69+
self.chat_history[0]
70+
if self.chat_history and self.chat_history[0]["role"] == "system"
71+
else None
72+
)
73+
74+
# 构造总结提示
75+
summarize_history = []
76+
if system_msg:
77+
summarize_history.append(system_msg)
78+
79+
# 添加要总结的对话内容(跳过第一条系统消息和最后5条消息)
80+
start_idx = 1 if system_msg else 0
81+
end_idx = len(self.chat_history) - 5
82+
83+
if end_idx > start_idx:
84+
summarize_history.append(
85+
{
86+
"role": "user",
87+
"content": f"请简洁总结以下对话的关键内容和重要结论,保留重要的上下文信息:\n\n{self._format_history_for_summary(self.chat_history[start_idx:end_idx])}",
88+
}
89+
)
90+
91+
# 调用 simple_chat 进行总结
92+
summary = await simple_chat(self.model, summarize_history)
93+
94+
# 重构聊天历史:系统消息 + 总结 + 最后5条消息
95+
new_history = []
96+
if system_msg:
97+
new_history.append(system_msg)
98+
99+
new_history.append(
100+
{"role": "assistant", "content": f"[历史对话总结] {summary}"}
101+
)
102+
103+
# 添加最后5条消息
104+
new_history.extend(self.chat_history[-5:])
105+
106+
self.chat_history = new_history
107+
logger.info(
108+
f"{self.__class__.__name__}:记忆清除完成,压缩至:{len(self.chat_history)}条记录"
109+
)
110+
else:
111+
logger.info(f"{self.__class__.__name__}:无需清除记忆,记录数量合理")
112+
113+
except Exception as e:
114+
logger.error(f"记忆清除失败,使用简单切片策略: {str(e)}")
115+
# 如果总结失败,回退到简单的切片策略
116+
self.chat_history = self.chat_history[:2] + self.chat_history[-5:]
117+
118+
def _format_history_for_summary(self, history: list[dict]) -> str:
119+
"""格式化历史记录用于总结"""
120+
formatted = []
121+
for msg in history:
122+
role = msg["role"]
123+
content = (
124+
msg["content"][:500] + "..."
125+
if len(msg["content"]) > 500
126+
else msg["content"]
127+
) # 限制长度
128+
formatted.append(f"{role}: {content}")
129+
return "\n".join(formatted)

backend/app/core/agents/coder_agent.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ async def run(self, prompt: str, subtask_title: str) -> CoderToWriter:
4040
if self.is_first_run:
4141
logger.info("首次运行,添加系统提示和数据集文件信息")
4242
self.is_first_run = False
43-
self.append_chat_history({"role": "system", "content": self.system_prompt})
43+
await self.append_chat_history(
44+
{"role": "system", "content": self.system_prompt}
45+
)
4446
# 当前数据集文件
45-
self.append_chat_history(
47+
await self.append_chat_history(
4648
{
4749
"role": "user",
4850
"content": f"当前文件夹下的数据集文件{get_current_files(self.work_dir, 'data')}",
@@ -51,7 +53,7 @@ async def run(self, prompt: str, subtask_title: str) -> CoderToWriter:
5153

5254
# 添加 sub_task
5355
logger.info(f"添加子任务提示: {prompt}")
54-
self.append_chat_history({"role": "user", "content": prompt})
56+
await self.append_chat_history({"role": "user", "content": prompt})
5557

5658
retry_count = 0
5759
last_error_message = ""
@@ -118,7 +120,9 @@ async def run(self, prompt: str, subtask_title: str) -> CoderToWriter:
118120
)
119121

120122
# 更新对话历史 - 添加助手的响应
121-
self.append_chat_history(response.choices[0].message.model_dump())
123+
await self.append_chat_history(
124+
response.choices[0].message.model_dump()
125+
)
122126
logger.info(response.choices[0].message.model_dump())
123127

124128
# 执行工具调用
@@ -132,7 +136,7 @@ async def run(self, prompt: str, subtask_title: str) -> CoderToWriter:
132136
# 添加工具执行结果
133137
if error_occurred:
134138
# 即使发生错误也要添加tool响应
135-
self.append_chat_history(
139+
await self.append_chat_history(
136140
{
137141
"role": "tool",
138142
"tool_call_id": tool_id,
@@ -152,14 +156,14 @@ async def run(self, prompt: str, subtask_title: str) -> CoderToWriter:
152156
SystemMessage(content="代码手反思纠正错误", type="error"),
153157
)
154158

155-
self.append_chat_history(
159+
await self.append_chat_history(
156160
{"role": "user", "content": reflection_prompt}
157161
)
158162
# 如果代码出错,返回重新开始
159163
continue
160164
else:
161165
# 成功执行的tool响应
162-
self.append_chat_history(
166+
await self.append_chat_history(
163167
{
164168
"role": "tool",
165169
"tool_call_id": tool_id,

backend/app/core/agents/coordinator_agent.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ def __init__(
1919

2020
async def run(self, ques_all: str) -> CoordinatorToModeler:
2121
"""用户输入问题 使用LLM 格式化 questions"""
22-
self.append_chat_history({"role": "system", "content": self.system_prompt})
23-
self.append_chat_history({"role": "user", "content": ques_all})
22+
await self.append_chat_history(
23+
{"role": "system", "content": self.system_prompt}
24+
)
25+
await self.append_chat_history({"role": "user", "content": ques_all})
2426

2527
response = await self.model.chat(
2628
history=self.chat_history,

backend/app/core/agents/modeler_agent.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ def __init__(
1818
self.system_prompt = MODELER_PROMPT
1919

2020
async def run(self, coordinator_to_modeler: CoordinatorToModeler) -> ModelerToCoder:
21-
self.append_chat_history({"role": "system", "content": self.system_prompt})
22-
self.append_chat_history(
21+
await self.append_chat_history(
22+
{"role": "system", "content": self.system_prompt}
23+
)
24+
await self.append_chat_history(
2325
{
2426
"role": "user",
2527
"content": json.dumps(coordinator_to_modeler.questions),

backend/app/core/agents/writer_agent.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ async def run(
5252

5353
if self.is_first_run:
5454
self.is_first_run = False
55-
self.append_chat_history({"role": "system", "content": self.system_prompt})
55+
await self.append_chat_history(
56+
{"role": "system", "content": self.system_prompt}
57+
)
5658

5759
if available_images:
5860
self.available_images = available_images
@@ -65,7 +67,7 @@ async def run(
6567
logger.info(f"{self.__class__.__name__}:开始:执行对话")
6668
self.current_chat_turns += 1 # 重置对话轮次计数器
6769

68-
self.append_chat_history({"role": "user", "content": prompt})
70+
await self.append_chat_history({"role": "user", "content": prompt})
6971

7072
# 获取历史消息用于本次对话
7173
response = await self.model.chat(
@@ -102,7 +104,7 @@ async def run(
102104
)
103105

104106
# 更新对话历史 - 添加助手的响应
105-
self.append_chat_history(response.choices[0].message.model_dump())
107+
await self.append_chat_history(response.choices[0].message.model_dump())
106108
ic(response.choices[0].message.model_dump())
107109

108110
try:
@@ -116,7 +118,7 @@ async def run(
116118
# TODO: pass to frontend
117119
papers_str = self.scholar.papers_to_str(papers)
118120
logger.info(f"搜索文献结果\n{papers_str}")
119-
self.append_chat_history(
121+
await self.append_chat_history(
120122
{
121123
"role": "tool",
122124
"content": papers_str,
@@ -143,14 +145,14 @@ async def summarize(self) -> str:
143145
总结对话内容
144146
"""
145147
try:
146-
self.append_chat_history(
148+
await self.append_chat_history(
147149
{"role": "user", "content": "请简单总结以上完成什么任务取得什么结果:"}
148150
)
149151
# 获取历史消息用于本次对话
150152
response = await self.model.chat(
151153
history=self.chat_history, agent_name=self.__class__.__name__
152154
)
153-
self.append_chat_history(
155+
await self.append_chat_history(
154156
{"role": "assistant", "content": response.choices[0].message.content}
155157
)
156158
return response.choices[0].message.content

frontend/src/pages/task/index.vue

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ import {
1010
TabsList,
1111
TabsTrigger,
1212
} from '@/components/ui/tabs'
13-
import {
14-
Card,
15-
CardContent,
16-
} from '@/components/ui/card'
1713
import CoderEditor from '@/components/AgentEditor/CoderEditor.vue'
1814
import WriterEditor from '@/components/AgentEditor/WriterEditor.vue'
1915
import ModelerEditor from '@/components/AgentEditor/ModelerEditor.vue'
@@ -33,12 +29,44 @@ const taskStore = useTaskStore()
3329
3430
const writerSequence = ref<string[]>([]);
3531
32+
// 项目运行时长相关
33+
const startTime = ref<number>(Date.now())
34+
const currentTime = ref<number>(Date.now())
35+
let timer: ReturnType<typeof setInterval> | null = null
36+
37+
// 格式化运行时长
38+
const formatDuration = (ms: number): string => {
39+
const seconds = Math.floor(ms / 1000)
40+
const hours = Math.floor(seconds / 3600)
41+
const minutes = Math.floor((seconds % 3600) / 60)
42+
const remainingSeconds = seconds % 60
43+
44+
if (hours > 0) {
45+
return `${hours}h ${minutes}m ${remainingSeconds}s`
46+
} else if (minutes > 0) {
47+
return `${minutes}m ${remainingSeconds}s`
48+
} else {
49+
return `${remainingSeconds}s`
50+
}
51+
}
52+
53+
// 计算运行时长
54+
const runningDuration = ref<string>('0s')
55+
const updateDuration = () => {
56+
currentTime.value = Date.now()
57+
runningDuration.value = formatDuration(currentTime.value - startTime.value)
58+
}
59+
3660
console.log('Task ID:', props.task_id)
3761
3862
onMounted(async () => {
3963
taskStore.connectWebSocket(props.task_id)
4064
const res = await getWriterSeque();
4165
writerSequence.value = Array.isArray(res.data) ? res.data : [];
66+
67+
// 开始计时
68+
timer = setInterval(updateDuration, 1000)
69+
updateDuration() // 立即更新一次
4270
})
4371
4472
const openFolder = async () => {
@@ -53,6 +81,11 @@ const openFolder = async () => {
5381
5482
onBeforeUnmount(() => {
5583
taskStore.closeWebSocket()
84+
// 清理计时器
85+
if (timer) {
86+
clearInterval(timer)
87+
timer = null
88+
}
5689
})
5790
5891
</script>
@@ -66,19 +99,25 @@ onBeforeUnmount(() => {
6699
<ResizableHandle />
67100
<ResizablePanel :default-size="60" class="h-full min-w-0">
68101
<div class="flex h-full flex-col min-w-0">
69-
<Tabs default-value="coder" class="w-full h-full flex flex-col">
102+
<Tabs default-value="modeler" class="w-full h-full flex flex-col">
103+
<!-- TODO: Agent 的状态 -->
70104
<div class="border-b px-4 py-1 flex justify-between">
71-
<TabsList class="">
72-
<TabsTrigger value="modeler" class="text-sm">
73-
ModelerAgent
74-
</TabsTrigger>
75-
<TabsTrigger value="coder" class="text-sm">
76-
CoderAgent
77-
</TabsTrigger>
78-
<TabsTrigger value="writer" class="text-sm">
79-
WriterAgent
80-
</TabsTrigger>
81-
</TabsList>
105+
<div class="flex items-center gap-4">
106+
<div class="text-sm text-gray-600">
107+
运行时长: <span class="font-mono text-blue-600">{{ runningDuration }}</span>
108+
</div>
109+
<TabsList>
110+
<TabsTrigger value="modeler" class="text-sm">
111+
ModelerAgent
112+
</TabsTrigger>
113+
<TabsTrigger value="coder" class="text-sm">
114+
CoderAgent
115+
</TabsTrigger>
116+
<TabsTrigger value="writer" class="text-sm">
117+
WriterAgent
118+
</TabsTrigger>
119+
</TabsList>
120+
</div>
82121
<!-- TODO: 其他选项 -->
83122

84123
<div class="flex justify-end gap-2">

0 commit comments

Comments
 (0)