Skip to content

Commit 0a5c824

Browse files
authored
Merge pull request #4 from jihe520/dev
support all model
2 parents eaa7c09 + ba3466c commit 0a5c824

25 files changed

+1175
-129
lines changed

.dockerignore

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# IDE settings
2+
.idea/
3+
.vscode/
4+
5+
# Git
6+
.git/
7+
.gitignore
8+
9+
# macOS
10+
.DS_Store
11+
12+
# Other temp files or OS-specific files
13+
*.swp
14+
Thumbs.db
15+
16+
docs/
17+
.cursor

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ backend/app/.DS_Store
66
._*
77
.Spotlight-V100
88
.Trashes
9+
.idea/

README.md

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,16 @@
4545
- [x] codeinterpreter 接入云端 如 e2b 等供应商..
4646
- [ ] 多语言: R 语言, matlab
4747
- [ ] 绘图 napki,draw.io
48+
- [ ] 添加 benchmark
4849

4950
## 视频demo
5051

5152
<video src="https://github.com/user-attachments/assets/954cb607-8e7e-45c6-8b15-f85e204a0c5d"></video>
5253

54+
> [!CAUTION]
55+
> 项目处于实验探索迭代demo阶段,有许多需要改进优化改进地方,我(项目作者)很忙,有时间会优化更新
56+
> 欢迎贡献
57+
5358
## 📖 使用教程
5459

5560
> 确保电脑中安装好 Python, Nodejs, **Redis** 环境
@@ -60,32 +65,21 @@
6065

6166
1. 配置模型
6267

63-
复制`/backend/.env.dev.example``/backend/.env.dev`(删除`.example` 后缀), 填写配置模型和 APIKEY
64-
[deepseek开发者平台](https://platform.deepseek.com/)
68+
复制`/backend/.env.dev.example``/backend/.env.dev`(删除`.example` 后缀)
69+
填写配置模型和 APIKEY
70+
推荐模型能力较强的、参数量大的模型。
6571

6672
```bash
67-
ENV=dev
68-
# 兼容 OpenAI 格式都行,具体看官方文档
69-
DEEPSEEK_API_KEY=
70-
DEEPSEEK_MODEL=
71-
DEEPSEEK_BASE_URL=
72-
# 模型最大问答次数
73-
MAX_CHAT_TURNS=60
74-
# 思考反思次数
75-
MAX_RETRIES=5
76-
77-
LOG_LEVEL=DEBUG
78-
DEBUG=true
73+
# support all model, check out https://docs.litellm.ai/docs/
74+
API_KEY=
75+
# gpt-4.1,deepseek/deepseek-chat
76+
MODEL=
7977
# 确保安装 Redis
80-
REDIS_URL=redis://localhost:6379/0
81-
REDIS_MAX_CONNECTIONS=20
82-
CORS_ALLOW_ORIGINS=http://localhost:5173,http://localhost:3000
8378
```
8479

8580
复制`/fronted/.env.example``/fronted/.env`(删除`.example` 后缀)
8681

8782

88-
推荐模型能力较强的、参数量大的模型。
8983

9084
2. 安装依赖
9185

backend/.dockerignore

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# backend/.dockerignore
2+
__pycache__/
3+
*.pyc
4+
*.pyo
5+
*.pyd
6+
.Python
7+
env/
8+
venv/
9+
.venv/
10+
*.egg-info/
11+
.DS_Store
12+
.pytest_cache/
13+
.ruff_cache/
14+
.mypy_cache/
15+
# Git
16+
.git/
17+
.gitignore
18+
# IDE
19+
.idea/
20+
.vscode/
21+
# macOS
22+
.DS_Store

backend/.env.dev.example

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
ENV=dev
2-
#兼容 OpenAI 格式都行,具体看官方文档
3-
DEEPSEEK_API_KEY=
4-
DEEPSEEK_MODEL=
5-
DEEPSEEK_BASE_URL=
2+
# support all model, check out https://docs.litellm.ai/docs/
3+
API_KEY=
4+
# gpt-4.1,deepseek/deepseek-chat
5+
MODEL=
6+
67
# 模型最大问答次数
78
MAX_CHAT_TURNS=60
89
# 思考反思次数
910
MAX_RETRIES=5
1011

11-
# 不需要填,默认调用本地 Python,建议不填,本地运行性能更好
12+
# 不需要填,默认调用本地 Python
1213
# E2B_API_KEY=
14+
SERVER_HOST=http://localhost:8000
1315

1416
LOG_LEVEL=DEBUG
1517
DEBUG=true

backend/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ RUN --mount=type=cache,target=/root/.cache/uv \
2222

2323
EXPOSE 8000
2424

25-
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--ws-ping-interval", "60", "--ws-ping-timeout", "120"]
25+
CMD ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--ws-ping-interval", "60", "--ws-ping-timeout", "120"]

backend/app/config/setting.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ def parse_cors(value: str) -> list[str]:
1717

1818
class Settings(BaseSettings):
1919
ENV: str
20-
DEEPSEEK_API_KEY: str
21-
DEEPSEEK_MODEL: str
22-
DEEPSEEK_BASE_URL: str
20+
API_KEY: str
21+
MODEL: str
22+
BASE_URL: Optional[str] = None
2323
MAX_CHAT_TURNS: int
2424
MAX_RETRIES: int
2525
E2B_API_KEY: Optional[str] = None
@@ -28,6 +28,7 @@ class Settings(BaseSettings):
2828
REDIS_URL: str
2929
REDIS_MAX_CONNECTIONS: int
3030
CORS_ALLOW_ORIGINS: Annotated[list[str] | str, BeforeValidator(parse_cors)]
31+
SERVER_HOST: str = "http://localhost:8000" # 默认值
3132

3233
model_config = SettingsConfigDict(
3334
env_file=".env.dev",

backend/app/core/agents.py

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ def __init__(
2626
model: LLM,
2727
max_chat_turns: int = 30, # 单个agent最大对话轮次
2828
user_output: UserOutput = None,
29+
max_memory: int = 20, # 最大记忆轮次
2930
) -> None:
3031
self.task_id = task_id
3132
self.model = model
3233
self.chat_history: list[dict] = [] # 存储对话历史
3334
self.max_chat_turns = max_chat_turns # 最大对话轮次
3435
self.current_chat_turns = 0 # 当前对话轮次计数器
3536
self.user_output = user_output
37+
self.max_memory = max_memory # 最大记忆轮次
3638

3739
async def run(self, prompt: str, system_prompt: str, sub_title: str) -> str:
3840
"""
@@ -68,11 +70,20 @@ async def run(self, prompt: str, system_prompt: str, sub_title: str) -> str:
6870
return error_msg
6971

7072
def append_chat_history(self, msg: dict) -> None:
73+
self.clear_memory()
7174
self.chat_history.append(msg)
7275
# self.user_output.data_recorder.append_chat_history(
7376
# msg, agent_name=self.__class__.__name__
7477
# )
7578

79+
def clear_memory(self):
80+
logger.info(f"{self.__class__.__name__}:清除记忆")
81+
if len(self.chat_history) <= self.max_memory:
82+
return
83+
84+
# 使用切片保留第一条和最后两条消息
85+
self.chat_history = self.chat_history[:2] + self.chat_history[-5:]
86+
7687

7788
class ModelerAgent(Agent): # 继承自Agent类而不是BaseModel
7889
def __init__(
@@ -207,18 +218,18 @@ async def run(self, prompt: str, subtask_title: str) -> CoderToWriter:
207218
error_message,
208219
) = await self.code_interpreter.execute_code(code)
209220

210-
# 记录执行结果
211-
212221
# 添加工具执行结果
213-
self.append_chat_history(
214-
{
215-
"role": "tool",
216-
"content": text_to_gpt,
217-
"tool_call_id": tool_id,
218-
}
219-
)
220-
# 代码执行错误
221222
if error_occurred:
223+
# 即使发生错误也要添加tool响应
224+
self.append_chat_history(
225+
{
226+
"role": "tool",
227+
"content": error_message,
228+
"tool_call_id": tool_id,
229+
"name": "execute_code",
230+
}
231+
)
232+
222233
logger.warning(f"代码执行错误: {error_message}")
223234
retry_count += 1
224235
logger.info(f"当前尝试次:{retry_count} / {self.max_retries}")
@@ -227,14 +238,24 @@ async def run(self, prompt: str, subtask_title: str) -> CoderToWriter:
227238

228239
await redis_manager.publish_message(
229240
self.task_id,
230-
SystemMessage(content="代码手反思错误", type="error"),
241+
SystemMessage(content="代码手反思纠正错误", type="error"),
231242
)
232243

233244
self.append_chat_history(
234245
{"role": "user", "content": reflection_prompt}
235246
)
236247
# 如果代码出错,返回重新开始
237248
continue
249+
else:
250+
# 成功执行的tool响应
251+
self.append_chat_history(
252+
{
253+
"role": "tool",
254+
"content": text_to_gpt,
255+
"tool_call_id": tool_id,
256+
"name": "execute_code",
257+
}
258+
)
238259

239260
# 检查任务完成情况时也计入对话轮次
240261
self.current_chat_turns += 1
@@ -326,7 +347,28 @@ async def run(
326347
image_prompt = f"\n可用的图片链接列表:\n{image_list}\n请在写作时适当引用这些图片链接。"
327348
prompt = prompt + image_prompt
328349

329-
return await super().run(prompt, self.system_prompt, sub_title)
350+
try:
351+
logger.info(f"{self.__class__.__name__}:开始:执行对话")
352+
self.current_chat_turns = 0 # 重置对话轮次计数器
353+
354+
# 更新对话历史
355+
self.append_chat_history({"role": "system", "content": self.system_prompt})
356+
self.append_chat_history({"role": "user", "content": prompt})
357+
358+
# 获取历史消息用于本次对话
359+
response = await self.model.chat(
360+
history=self.chat_history,
361+
agent_name=self.__class__.__name__,
362+
sub_title=sub_title,
363+
)
364+
response_content = response.choices[0].message.content
365+
self.chat_history.append({"role": "assistant", "content": response_content})
366+
logger.info(f"{self.__class__.__name__}:完成:执行对话")
367+
return response_content
368+
except Exception as e:
369+
error_msg = f"执行过程中遇到错误: {str(e)}"
370+
logger.error(f"Agent执行失败: {str(e)}")
371+
return error_msg
330372

331373
async def summarize(self) -> str:
332374
"""

backend/app/core/functions.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from typing import List, Dict, Any
2+
from semanticscholar import SemanticScholar, PaginatedResults
3+
14
tools = [
25
{
36
"type": "function",
@@ -28,3 +31,21 @@
2831
# TODO: read files
2932

3033
# TODO: get_cites
34+
35+
36+
def search_papers(query: str) -> List[Dict[str, Any]]:
37+
"""Search for papers using a query string."""
38+
sch = SemanticScholar()
39+
results: PaginatedResults = sch.search_paper(query, limit=10)
40+
return [
41+
{
42+
"title": paper.title,
43+
"abstract": paper.abstract,
44+
"authorsName": [author.name for author in paper.authors],
45+
"citations": [citation.title for citation in paper.citations],
46+
}
47+
for paper in results
48+
]
49+
50+
51+
## writeragent tools

0 commit comments

Comments
 (0)