update start_long_term desc: remove single-call limit, add 15-turn rule

This commit is contained in:
Jiaqing Liang
2026-03-02 17:25:22 +08:00
parent 82991c4a69
commit 066a2995e4
5 changed files with 17 additions and 8 deletions

View File

@@ -69,6 +69,7 @@ def agent_runner_loop(client, system_prompt, user_input, handler, tools_schema,
showarg = get_pretty_json(args)
if not verbose and len(showarg) > 200: showarg = showarg[:200] + ' ...'
yield f"🛠️ **正在调用工具:** `{tool_name}` 📥**参数:**\n````text\n{showarg}\n````\n"
handler.current_turn = turn + 1
gen = handler.dispatch(tool_name, args, response)
if verbose:
yield '`````\n'

View File

@@ -43,7 +43,7 @@
"name": "web_execute_js",
"description": "万能网页操控工具。通过执行 JavaScript 脚本实现对浏览器的完全控制如点击、滚动、提取特定数据。鼓励在有把握情况下记忆中有selector/做法等精准使用以减少web_scan调用。执行结果可选择保存到本地文件进行后续分析。",
"parameters": {"type": "object", "properties": {
"script": {"type": "string", "description": "要执行的 JavaScript 代码。"},
"script": {"type": "string", "description": "要执行的 JavaScript 代码或JS文件路径。"},
"save_to_file": {"type": "string", "description": "可选。将 JS 执行结果js_return保存到的文件路径。该功能不支持 await 等异步结果。"}}, "required": ["script"]}
}},
{"type": "function", "function": {
@@ -62,7 +62,7 @@
}},
{"type": "function", "function": {
"name": "start_long_term_update",
"description": "准备开始提炼记忆。发现值得长期记忆的信息(环境事实/用户偏好/避坑经验)时调用此工具。一次用户对话只允许调用一次,已记忆更新或在自主流程内时无需调用。",
"description": "准备开始提炼记忆。发现值得长期记忆的信息(环境事实/用户偏好/避坑经验)时调用此工具。已记忆更新或在自主流程内时无需调用。超15轮完成的任务必须调用以沉淀经验。",
"parameters": {"type": "object", "properties": {}}}
}
]

6
ga.py
View File

@@ -247,7 +247,7 @@ class GenericAgentHandler(BaseHandler):
self.parent = parent
self.key_info = ""
self.related_sop = ""
self.cwd = cwd
self.cwd = cwd; self.current_turn = 0
self.history_info = last_history if last_history else []
self.code_stop_signal = []
@@ -313,6 +313,9 @@ class GenericAgentHandler(BaseHandler):
'''
script = args.get("script", "")
if not script: return StepOutcome(None, next_prompt="[Error] Empty script param. Check your tool call arguments.")
abs_path = self._get_abs_path(script.strip())
if os.path.isfile(abs_path):
with open(abs_path, 'r', encoding='utf-8') as f: script = f.read()
save_to_file = args.get("save_to_file", "")
switch_tab_id = args.get("switch_tab_id") or args.get("tab_id")
result = web_execute_js(script, switch_tab_id=switch_tab_id)
@@ -471,6 +474,7 @@ class GenericAgentHandler(BaseHandler):
def _get_anchor_prompt(self):
h_str = "\n".join(self.history_info[-20:])
prompt = f"\n### [WORKING MEMORY]\n<history>\n{h_str}\n</history>"
prompt += f"\nCurrent turn: {self.current_turn}\n"
if self.key_info: prompt += f"\n<key_info>{self.key_info}</key_info>"
if self.related_sop: prompt += f"\n有不清晰的地方请再次读取{self.related_sop}"
try: print(prompt)

View File

@@ -10,6 +10,8 @@
3. **禁止存储易变状态 (No Volatile State)**
* **定义**:严禁存储随时间/会话高频变化的数据。
* **示例**:当前时间戳、临时 Session ID、正在运行的 PID、某个具体绝对路径、连接的设备信息
4. **最小充分指针 (Minimum Sufficient Pointer)**
* 上层只留能定位下层的最短标识,多一词即冗余。
---
## 记忆层级架构
```
@@ -24,7 +26,7 @@ L3: ../memory/ (记录库层 - 包含 .md/.py 等各类文件)
### L1全局内存索引 (global_mem_insight.txt)
**职责**:为 L2 和 L3 提供极简导航索引,确保关键能力可被发现。
**特征**
- 体积限制:≤ 30 行(硬约束)
- 体积限制:≤ 30 行(硬约束),严禁填写细节(除非极高频任务)
- 内容:两层「场景关键词→记忆定位」映射 + RULES红线规则 + 高频犯错点)
- 第一层:高频场景 key→value直接给出 sop/py/L2 section 名),自包含可只写一个词
- 第二层:低频场景仅列关键词,需要时 read L2 或 ls L3 自行定位
@@ -41,7 +43,7 @@ L3: ../memory/ (记录库层 - 包含 .md/.py 等各类文件)
**特征**
- 趋势:随环境扩展而膨胀(可接受)
- 内容:按 `## [SECTION]` 组织的事实条目
- 同步:变化时更新 L1 的相应 TOPIC 导航行
- 同步:变化时更新 L1 的相应 TOPIC 导航行,只能导航
**禁止**:禁止存储易变状态、禁止存储猜测、严禁存储大模型可推理的通用常识
---
### L3任务级精简记录库 (../memory/)
@@ -61,6 +63,9 @@ L3: ../memory/ (记录库层 - 包含 .md/.py 等各类文件)
| L2/L3 删除场景 | 删除对应层的关键词/映射行 |
| L2/L3 修改值 | 若不影响场景定位则不动 L1 |
| 发现通用避坑规律 | 压缩为一句加入 RULES |
> **同步红线**L1 只写关键词/名称,禁搬细节。
---
## 信息分类快速决策树
```

View File

@@ -101,6 +101,7 @@ class LLMSession:
def _endpoint(self, path):
if self.api_base.endswith('/v1'): return f"{self.api_base}/{path.lstrip('/')}"
if self.api_base.endswith('$'): return f"{self.api_base.rstrip('$')}/{path.lstrip('/')}"
return f"{self.api_base}/v1/{path.lstrip('/')}"
def _retry_delay(self, resp, attempt):
@@ -211,9 +212,7 @@ class LLMSession:
try: body = (resp.text or "").strip()
except: body = ""
body = body[:1200] if body else "<empty>"
rid = ""
retry_after = ""
ct = ""
rid = ""; retry_after = ""; ct = ""
try:
h = resp.headers or {}
rid = h.get("x-request-id") or h.get("request-id") or ""