Skip to content

Commit f901ec4

Browse files
authored
Merge pull request #3 from jihe520/dev
Dev
2 parents b071e75 + 6b3e755 commit f901ec4

36 files changed

+4059
-612
lines changed

README.md

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,105 @@
1-
## Test
1+
<h1 align="center">🤖 MathModelAgent 📐</h1>
2+
<p align="center">
3+
<img src="./docs/icon.png" height="250px">
4+
</p>
5+
<h4 align="center">
6+
专为数学建模设计的 Agent<br>
7+
自动完成数学建模,生成一份完整的可以直接提交的论文。
8+
</h4>
9+
10+
<h5 align="center">简体中文 | <a href="README_EN.md">English</a></h5>
11+
12+
## 🌟 愿景:
13+
14+
3 天的比赛时间变为 1 小时 <br>
15+
自动完整一份可以获奖级别的建模论文
16+
17+
<p align="center">
18+
<img src="./docs/webui.png">
19+
</p>
20+
21+
## ✨ 功能特性
22+
23+
- 🔍 自动分析问题,数学建模,编写代码,纠正错误,撰写论文
24+
- 💻 本地代码解释器
25+
- 📝 生成一份编排好格式的论文
26+
- 🤝 muti-agents: ~~建模手~~,代码手(反思模块,本地代码解释器),论文手
27+
- 🔄 muti-llms: 每个agent设置不同的模型
28+
- 💰 成本低 agentless(单次任务成本约 1 rmb)
29+
30+
## 🚀 后期计划
31+
32+
- [x] 添加并完成 webui、cli
33+
- [ ] 完善的教程、文档
34+
- [ ] 提供 web 服务
35+
- [ ] 英文支持(美赛)
36+
- [ ] 集成 latex 模板
37+
- [ ] 接入视觉模型
38+
- [ ] 添加正确文献引用
39+
- [ ] 更多测试案例
40+
- [ ] docker 部署
41+
- [ ] 引入用户的交互(选择模型,重写等等)
42+
- [ ] codeinterpreter 接入云端 如 e2b 等供应商..
43+
- [ ] 多语言: R 语言, matlab
44+
45+
clone 项目后,下载**Todo Tree**插件,可以查看代码中所有具体位置的 todo
46+
47+
## 视频demo
48+
49+
<video src="https://github.com/user-attachments/assets/10b3145a-feb7-4894-aaca-30d44bb35b9e"></video>
50+
51+
## 📖 使用教程
52+
53+
1. 安装依赖
54+
55+
```bash
56+
git clone https://github.com/jihe520/MathModelAgent.git # 克隆项目
57+
pip install uv # 推荐使用 uv 管理 python 项目
58+
uv venv # 创建虚拟环境
59+
uv sync # 安装依赖
60+
```
61+
62+
2. 配置模型
63+
64+
复制`/config/config.toml.example``/config/config.toml`, 填写配置模型和 APIKEY
65+
[deepseek开发者平台](https://platform.deepseek.com/)
66+
67+
推荐模型能力较强的、参数量大的模型。
68+
69+
3. 运行测试 和 启动项目
70+
71+
```bash
72+
uv run example.py # 简单测试能否正确运行
73+
uv run webui.py # 推荐: 启动 webui
74+
uv run terminal.py # 启动终端项目
75+
```
76+
77+
运行的结果在`/project/work_dir/`目录下
78+
79+
## 🤝 贡献
80+
81+
- 项目处于**开发阶段**(我有时间就会更新),变更较多,还存在许多 Bug,我正着手修复。
82+
- 欢迎提交 issues 和 PRs
83+
- 需求参考 后期计划
84+
85+
## 📄 版权License
86+
87+
请勿商业用途,商业用途联系我(作者)
88+
89+
## 🙏 Reference
90+
91+
Thanks to the following projects:
92+
- [OpenCodeInterpreter](https://github.com/OpenCodeInterpreter/OpenCodeInterpreter/tree/main)
93+
- [TaskWeaver](https://github.com/microsoft/TaskWeaver)
94+
- [Code-Interpreter](https://github.com/MrGreyfun/Local-Code-Interpreter/tree/main)
95+
- [Latex](https://github.com/Veni222987/MathModelingLatexTemplate/tree/main)
96+
97+
98+
## 其他
99+
100+
感谢赞助
101+
[danmo-tyc](https://github.com/danmo-tyc)
102+
103+
有问题可以进群问
104+
105+
<img src="./docs/qq.jpg" height="400px">

README_EN.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<h1 align="center">🤖 MathModelAgent 📐</h1>
2+
<p align="center">
3+
<img src="./docs/icon.png" height="250px">
4+
</p>
5+
<h4 align="center">
6+
An agent designed for mathematical modeling<br>
7+
Automatically complete mathematical modeling and generate a ready-to-submit paper.
8+
</h4>
9+
10+
<br>
11+
<h5 align="center"> <a href="README.md">简体中文</a> | English </h5>
12+
13+
## Vision:
14+
3 days to 1 hour <br>
15+
Automatically generate an award-worthy mathematical modeling paper
16+
17+
## ✨ Features
18+
19+
- 🔍 Automatic problem analysis, mathematical modeling, code writing, error correction, and paper writing
20+
- 💻 Local code interpreter
21+
- 📝 Generate a well-formatted paper
22+
- 🤝 Multi-agents: ~~modeling expert~~, coding expert (reflection module, local code interpreter), paper expert
23+
- 🔄 Multi-llms: Different models for each agent
24+
25+
## 🚀 Future Plans
26+
27+
- [ ] Comprehensive tutorials and documentation
28+
- [ ] Web service
29+
- [ ] English support (MCM/ICM)
30+
- [ ] LaTeX template integration
31+
- [ ] Vision model integration
32+
- [ ] Proper citation implementation
33+
- [ ] More test cases
34+
- [ ] Docker deployment
35+
- [ ] User interaction (model selection, rewriting, etc.)
36+
- [ ] Cloud integration for code interpreter (e.g., e2b providers)
37+
38+
After cloning the project, install the **Todo Tree** plugin to view all specific todo locations in the code
39+
40+
## Video Demo
41+
42+
<video src="https://github.com/user-attachments/assets/10b3145a-feb7-4894-aaca-30d44bb35b9e"></video>
43+
44+
45+
## 📖 Usage Guide
46+
47+
1. Install Dependencies
48+
```bash
49+
git clone https://github.com/jihe520/MathModelAgent.git
50+
pip install uv
51+
uv venv # create venv
52+
uv sync # install dependencies
53+
```
54+
2. Configure Model
55+
Copy `/config/config.toml.example` to `/config/config.toml` and fill in the model configuration
56+
57+
Recommend using models with strong capabilities and large parameter counts.
58+
59+
3. Run Tests and Start Project
60+
```bash
61+
uv run example.py # simple test to verify correct operation
62+
uv run main.py # complete project
63+
```
64+
65+
Results will be in the `/project/work_dir/` directory
66+
67+
## 🤝 Contribution
68+
69+
- Project is in **development stage** (I update when time permits), with frequent changes and some bugs that I'm working to fix.
70+
- Issues and PRs are welcome
71+
- For requirements, refer to Future Plans
72+
73+
## 📄 License
74+
75+
Not for commercial use. Contact me (author) for commercial purposes.
76+
77+
## 🙏 Reference
78+
Thanks to the following projects:
79+
- [OpenCodeInterpreter](https://github.com/OpenCodeInterpreter/OpenCodeInterpreter/tree/main)
80+
- [TaskWeaver](https://github.com/microsoft/TaskWeaver)
81+
- [Code-Interpreter](https://github.com/MrGreyfun/Local-Code-Interpreter/tree/main)
82+
- [Latex](https://github.com/Veni222987/MathModelingLatexTemplate/tree/main)

backend/app/core/agents.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def __init__(
3434
self.current_chat_turns = 0 # 当前对话轮次计数器
3535
self.user_output = user_output
3636

37-
async def run(self, prompt: str, system_prompt: str) -> str:
37+
async def run(self, prompt: str, system_prompt: str, sub_title: str) -> str:
3838
"""
3939
执行agent的对话并返回结果和总结
4040
@@ -54,7 +54,9 @@ async def run(self, prompt: str, system_prompt: str) -> str:
5454

5555
# 获取历史消息用于本次对话
5656
response = await self.model.chat(
57-
history=self.chat_history, agent_name=self.__class__.__name__
57+
history=self.chat_history,
58+
agent_name=self.__class__.__name__,
59+
sub_title=sub_title,
5860
)
5961
response_content = response.choices[0].message.content
6062
self.chat_history.append({"role": "assistant", "content": response_content})
@@ -140,7 +142,7 @@ async def run(self, prompt: str, subtask_title: str) -> CoderToWriter:
140142
f"Failed to complete task after {self.max_retries} attempts. Last error: {last_error_message}"
141143
)
142144

143-
# try:
145+
# try:
144146
while (
145147
not task_completed
146148
and retry_count < self.max_retries
@@ -189,6 +191,7 @@ async def run(self, prompt: str, subtask_title: str) -> CoderToWriter:
189191
)
190192

191193
# 执行工具调用
194+
logger.warning("执行工具调用")
192195
(
193196
text_to_gpt,
194197
error_occurred,
@@ -207,6 +210,8 @@ async def run(self, prompt: str, subtask_title: str) -> CoderToWriter:
207210
)
208211

209212
if error_occurred:
213+
logger.warning("代码执行错误")
214+
210215
retry_count += 1
211216
last_error_message = error_message
212217
reflection_prompt = get_reflection_prompt(error_message, code)
@@ -224,6 +229,8 @@ async def run(self, prompt: str, subtask_title: str) -> CoderToWriter:
224229
# 检查任务完成情况时也计入对话轮次
225230
self.current_chat_turns += 1
226231
# 使用所有执行结果生成检查提示
232+
logger.warning("判断是否完成")
233+
227234
completion_check_prompt = get_completion_check_prompt(
228235
prompt, text_to_gpt
229236
)
@@ -245,6 +252,7 @@ async def run(self, prompt: str, subtask_title: str) -> CoderToWriter:
245252
hasattr(completion_response.choices[0].message, "tool_calls")
246253
and completion_response.choices[0].message.tool_calls
247254
):
255+
logger.warning("没有调用工具,代表已经完成了")
248256
task_completed = True
249257
return completion_response.choices[0].message.content
250258

@@ -282,28 +290,25 @@ async def run(
282290
self,
283291
prompt: str,
284292
available_images: list[str] = None,
285-
static_prefix: str = "/static/",
293+
sub_title: str = None,
286294
) -> str:
287295
"""
288296
执行写作任务
289297
Args:
290298
prompt: 写作提示
291299
available_images: 可用的图片相对路径列表(如 20250420-173744-9f87792c/编号_分布.png)
292-
static_prefix: 静态资源前缀
300+
sub_title: 子任务标题
293301
"""
302+
logger.info(f"subtitle是:{sub_title}")
303+
294304
if available_images:
295305
self.available_images = available_images
296306
# 拼接成完整URL
297-
image_list = "\n".join(
298-
[
299-
f"- {static_prefix}{img if img.startswith('/') else '/' + img}"
300-
for img in available_images
301-
]
302-
)
307+
image_list = ",".join(available_images)
303308
image_prompt = f"\n可用的图片链接列表:\n{image_list}\n请在写作时适当引用这些图片链接。"
304309
prompt = prompt + image_prompt
305310

306-
return await super().run(prompt, self.system_prompt)
311+
return await super().run(prompt, self.system_prompt, sub_title)
307312

308313
async def summarize(self) -> str:
309314
"""

backend/app/core/llm.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import json
2+
from app.utils.common_utils import transform_link
23
from openai import OpenAI
34
from app.utils.log_util import logger
45
import time
56
from app.schemas.response import AgentMessage, CoderMessage, WriterMessage
67
from app.utils.enums import AgentType
78
from app.utils.redis_manager import redis_manager
9+
import re
810

911

1012
class LLM:
@@ -32,7 +34,10 @@ async def chat(
3234
retry_delay: float = 1.0, # 添加重试延迟
3335
top_p: float | None = None, # 添加top_p参数,
3436
agent_name: str = "NO_NAME", # CoderAgent or WriterAgent
37+
sub_title: str | None = None,
3538
) -> str:
39+
logger.info(f"subtitle是:{sub_title}")
40+
3641
kwargs = {
3742
"model": self.model,
3843
"messages": history,
@@ -51,10 +56,11 @@ async def chat(
5156
for attempt in range(max_retries):
5257
try:
5358
completion = self.client.chat.completions.create(**kwargs)
59+
logger.info(f"API返回: {completion}")
5460
if not completion or not hasattr(completion, "choices"):
5561
raise ValueError("无效的API响应")
5662
self.chat_count += 1
57-
await self.analyse_completion(completion, agent_name)
63+
await self.analyse_completion(completion, agent_name, sub_title)
5864
return completion
5965
except json.JSONDecodeError:
6066
logger.error(f"第{attempt + 1}次重试: API返回无效JSON")
@@ -64,7 +70,9 @@ async def chat(
6470
logger.debug(f"请求参数: {kwargs}")
6571
raise # 如果所有重试都失败,则抛出异常
6672

67-
async def analyse_completion(self, completion, agent_name):
73+
async def analyse_completion(self, completion, agent_name, sub_title):
74+
logger.info(f"subtitle是:{sub_title}")
75+
6876
code = ""
6977
if (
7078
hasattr(completion.choices[0].message, "tool_calls")
@@ -73,13 +81,22 @@ async def analyse_completion(self, completion, agent_name):
7381
tool_call = completion.choices[0].message.tool_calls[0]
7482
if tool_call.function.name == "execute_code":
7583
code = json.loads(tool_call.function.arguments)["code"]
76-
await self.send_message(agent_name, completion.choices[0].message.content, code)
84+
(
85+
await self.send_message(
86+
agent_name, completion.choices[0].message.content, code, sub_title
87+
)
88+
)
7789

78-
async def send_message(self, agent_name, content, code=""):
90+
async def send_message(self, agent_name, content, code="", sub_title=None):
91+
logger.info(f"subtitle是:{sub_title}")
7992
if agent_name == "CoderAgent":
8093
agent_msg: CoderMessage = CoderMessage(content=content, code=code)
8194
elif agent_name == "WriterAgent":
82-
agent_msg: WriterMessage = WriterMessage(content=content)
95+
# 处理 Markdown 格式的图片语法
96+
content = transform_link(self.task_id, content)
97+
agent_msg: WriterMessage = WriterMessage(
98+
content=content, sub_title=sub_title
99+
)
83100
else:
84101
raise ValueError(f"无效的agent_name: {agent_name}")
85102

backend/app/core/prompts.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ def get_writer_prompt(
7575
skill:熟练掌握{format_output}排版,
7676
output:你需要按照要求的格式排版,只输出{format_output}排版的内容
7777
78-
1. 当你输入图像引用时候,你需要将用户输入的文件名称路径切换为相对路径
79-
如用户输入文件路径image_name.png,你转化为../jupyter/image_name.png,就可正确引用显示
80-
2. 你不需要输出markdown的这个```markdown格式,只需要输出markdown的内容
81-
3. 严格按照参考用户输入的格式模板以及**正确的编号顺序**
82-
4. 不需要询问用户
83-
5. 当提到图片时,请使用提供的图片列表中的文件名
78+
1. 当你输入图像引用时候,使用![image_name](image_name.png)
79+
2. 你不需要输出markdown的这个```markdown格式,只需要输出markdown的内容,
80+
3. Latex公式使用$$ $$包裹
81+
4. 严格按照参考用户输入的格式模板以及**正确的编号顺序**
82+
5. 不需要询问用户
83+
6. 当提到图片时,请使用提供的图片列表中的文件名
8484
"""
8585

8686

backend/app/core/workflow.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ async def execute(self, problem: Problem):
126126
writer_response = await writer_agent.run(
127127
writer_prompt,
128128
available_images=await e2b_code_interpreter.get_created_images(key),
129+
sub_title=key,
129130
)
130131

131132
await redis_manager.publish_message(
@@ -156,7 +157,7 @@ async def execute(self, problem: Problem):
156157
comp_template=problem.comp_template,
157158
format_output=problem.format_output,
158159
)
159-
writer_response = await writer_agent.run(value)
160+
writer_response = await writer_agent.run(prompt=value, sub_title=key)
160161
user_output.set_res(key, writer_response)
161162

162163
logger.info(user_output.get_res())

0 commit comments

Comments
 (0)