rename sidercall.py to llmcore.py; add cache-aware cd to compress_history_tags
This commit is contained in:
@@ -136,7 +136,7 @@ The agent starts with 7 primitive tools. Through `code_run`, it can install pack
|
|||||||
**Core engine** (runs the agent):
|
**Core engine** (runs the agent):
|
||||||
- `agent_loop.py` — Sense-Think-Act loop (92 lines)
|
- `agent_loop.py` — Sense-Think-Act loop (92 lines)
|
||||||
- `ga.py` — Tool definitions and execution
|
- `ga.py` — Tool definitions and execution
|
||||||
- `sidercall.py` — LLM communication (multi-backend)
|
- `llmcore.py` — LLM communication (multi-backend)
|
||||||
- `agentmain.py` — Session orchestration
|
- `agentmain.py` — Session orchestration
|
||||||
|
|
||||||
**Interface** (talk to the agent):
|
**Interface** (talk to the agent):
|
||||||
@@ -255,7 +255,7 @@ Agent 拥有 7 个原子工具:`code_run`(执行任意代码)、`file_read
|
|||||||
**核心引擎**:
|
**核心引擎**:
|
||||||
- `agent_loop.py` — 感知-思考-行动循环(92 行)
|
- `agent_loop.py` — 感知-思考-行动循环(92 行)
|
||||||
- `ga.py` — 工具定义与执行
|
- `ga.py` — 工具定义与执行
|
||||||
- `sidercall.py` — LLM 通信(多后端)
|
- `llmcore.py` — LLM 通信(多后端)
|
||||||
- `agentmain.py` — 会话编排
|
- `agentmain.py` — 会话编排
|
||||||
|
|
||||||
**交互界面**:
|
**交互界面**:
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ if sys.stderr is None: sys.stderr = open(os.devnull, "w")
|
|||||||
elif hasattr(sys.stderr, 'reconfigure'): sys.stderr.reconfigure(errors='replace')
|
elif hasattr(sys.stderr, 'reconfigure'): sys.stderr.reconfigure(errors='replace')
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||||
|
|
||||||
from sidercall import SiderLLMSession, LLMSession, ToolClient, ClaudeSession, XaiSession
|
from llmcore import SiderLLMSession, LLMSession, ToolClient, ClaudeSession, XaiSession
|
||||||
from agent_loop import agent_runner_loop, StepOutcome, BaseHandler
|
from agent_loop import agent_runner_loop, StepOutcome, BaseHandler
|
||||||
from ga import GenericAgentHandler, smart_format, get_global_memory, format_error
|
from ga import GenericAgentHandler, smart_format, get_global_memory, format_error
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ class GeneraticAgent:
|
|||||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
temp_dir = os.path.join(script_dir, 'temp')
|
temp_dir = os.path.join(script_dir, 'temp')
|
||||||
if not os.path.exists(temp_dir): os.makedirs(temp_dir)
|
if not os.path.exists(temp_dir): os.makedirs(temp_dir)
|
||||||
from sidercall import mykeys
|
from llmcore import mykeys
|
||||||
llm_sessions = []
|
llm_sessions = []
|
||||||
for k, cfg in mykeys.items():
|
for k, cfg in mykeys.items():
|
||||||
if not any(x in k for x in ['api', 'config', 'cookie']): continue
|
if not any(x in k for x in ['api', 'config', 'cookie']): continue
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
- Python 3.8+
|
- Python 3.8+
|
||||||
- 本项目完整代码
|
- 本项目完整代码
|
||||||
- LLM API 密钥(Claude/OpenAI 等,已在 `sidercall/mykeys` 中配置)
|
- LLM API 密钥(Claude/OpenAI 等,已在 `llmcore/mykeys` 中配置)
|
||||||
|
|
||||||
### 安装依赖
|
### 安装依赖
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@ fs_allowed_users = [
|
|||||||
|
|
||||||
### 确认 LLM 配置
|
### 确认 LLM 配置
|
||||||
|
|
||||||
确保 `sidercall/mykeys` 中已配置 LLM API 密钥:
|
确保 `llmcore/mykeys` 中已配置 LLM API 密钥:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# 示例:Claude API
|
# 示例:Claude API
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||||
from sidercall import SiderLLMSession, LLMSession, ToolClient
|
from llmcore import SiderLLMSession, LLMSession, ToolClient
|
||||||
|
|
||||||
|
|
||||||
ask = SiderLLMSession().ask
|
ask = SiderLLMSession().ask
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ mykeys = _load_mykeys()
|
|||||||
proxy = mykeys.get("proxy", 'http://127.0.0.1:2082')
|
proxy = mykeys.get("proxy", 'http://127.0.0.1:2082')
|
||||||
proxies = {"http": proxy, "https": proxy} if proxy else None
|
proxies = {"http": proxy, "https": proxy} if proxy else None
|
||||||
|
|
||||||
def compress_history_tags(messages, keep_recent=4, max_len=200):
|
def compress_history_tags(messages, keep_recent=10, max_len=500):
|
||||||
"""Compress <thinking>/<tool_use>/<tool_result> tags in older messages to save tokens."""
|
"""Compress <thinking>/<tool_use>/<tool_result> tags in older messages to save tokens."""
|
||||||
|
compress_history_tags._cd = getattr(compress_history_tags, '_cd', 0) + 1
|
||||||
|
if compress_history_tags._cd % 5 != 0: return messages
|
||||||
for i, msg in enumerate(messages):
|
for i, msg in enumerate(messages):
|
||||||
if i < len(messages) - keep_recent and 'orig' not in msg:
|
if i < len(messages) - keep_recent and 'orig' not in msg:
|
||||||
msg['orig'] = msg['prompt']
|
msg['orig'] = msg['prompt']
|
||||||
@@ -47,7 +49,7 @@ class SiderLLMSession:
|
|||||||
return full_text
|
return full_text
|
||||||
|
|
||||||
class ClaudeSession:
|
class ClaudeSession:
|
||||||
def __init__(self, api_key, api_base, model="claude-opus", context_win=10000):
|
def __init__(self, api_key, api_base, model="claude-opus", context_win=12000):
|
||||||
self.api_key, self.api_base, self.default_model, self.context_win = api_key, api_base.rstrip('/'), model, context_win
|
self.api_key, self.api_base, self.default_model, self.context_win = api_key, api_base.rstrip('/'), model, context_win
|
||||||
self.raw_msgs, self.lock = [], threading.Lock()
|
self.raw_msgs, self.lock = [], threading.Lock()
|
||||||
def _trim_messages(self, messages):
|
def _trim_messages(self, messages):
|
||||||
@@ -96,7 +98,7 @@ class ClaudeSession:
|
|||||||
return _ask_gen() if stream else ''.join(list(_ask_gen()))
|
return _ask_gen() if stream else ''.join(list(_ask_gen()))
|
||||||
|
|
||||||
class LLMSession:
|
class LLMSession:
|
||||||
def __init__(self, api_key, api_base, model, context_win=12000, proxy=None, api_mode="chat_completions",
|
def __init__(self, api_key, api_base, model, context_win=16000, proxy=None, api_mode="chat_completions",
|
||||||
max_retries=2, connect_timeout=10, read_timeout=120):
|
max_retries=2, connect_timeout=10, read_timeout=120):
|
||||||
self.api_key = api_key; self.api_base = api_base.rstrip('/'); self.default_model = model
|
self.api_key = api_key; self.api_base = api_base.rstrip('/'); self.default_model = model
|
||||||
self.context_win = context_win; self.raw_msgs = []; self.messages = []
|
self.context_win = context_win; self.raw_msgs = []; self.messages = []
|
||||||
@@ -1,87 +1,38 @@
|
|||||||
# 自主行动 SOP (探测-报告-执行)
|
# 自主行动 SOP
|
||||||
|
|
||||||
⚠️ **路径警告**:autonomous_reports 在 temp/ 下,用`./autonomous_reports/`访问,**不是**`../memory/autonomous_reports/`或`../autonomous_reports/`!
|
|
||||||
|
|
||||||
授权你进行自主行动,只要不对环境造成副作用都可进行。
|
|
||||||
首先根据有无TODO确定**执行模式**或**任务规划模式**
|
|
||||||
如有TODO,进入**执行模式**,取一条TODO执行,完成后本轮结束(不继续执行下一条);
|
|
||||||
如果没有TODO,进入**任务规划模式**,深入分析并形成多个有价值的自主探索任务。规划完成后本轮结束,待下次自主行动执行。
|
|
||||||
|
|
||||||
|
⚠️ **路径警告**:autonomous_reports 在 temp/ 下,用`./autonomous_reports/`访问,**不是**`../memory/autonomous_reports/`或`../autonomous_reports/`!TODO在cwd下。
|
||||||
报告存于 `./autonomous_reports/`,文件名 `RXX_简短描述.md`(XX从 history.txt 推断自增)。
|
报告存于 `./autonomous_reports/`,文件名 `RXX_简短描述.md`(XX从 history.txt 推断自增)。
|
||||||
|
|
||||||
## 任务规划模式
|
授权你进行自主行动,只要不对环境造成副作用都可进行。
|
||||||
- **有TODO**:cwd下 `TODO.txt` 有待执行条目 → 直接跳到「执行流程」
|
|
||||||
|
|
||||||
价值公式:**「AI训练数据无法覆盖」×「对未来协作有持久收益」**。核心产出是记忆——有价值的发现整理为记忆更新提案纳入报告。
|
## 任务选择
|
||||||
|
- 有 `./TODO.txt`(temp根目录)未完成条目 → 取**一条**,直接进入执行,其他条目下次执行
|
||||||
|
- 无 TODO → 读 `autonomous_operation_sop/task_planning.md` 规划,下次执行
|
||||||
|
- 不连续两次选相同子任务
|
||||||
|
|
||||||
流程入口:
|
价值公式:**「AI训练数据无法覆盖」×「对未来协作有持久收益」**
|
||||||
- **无TODO → 进入任务规划模式**(本轮不执行任务,专注规划):
|
|
||||||
0. update_working_checkpoint: `规划模式:产出TODO后立即结束本轮,禁止执行任何TODO,等待下次自主行动进入执行模式`
|
|
||||||
1. ⚠️ **批判性读history.txt**:90%历史任务是低价值的,读取目的是**识别失败模式并避免**,而非寻找模仿对象
|
|
||||||
- 识别低价值模式:浅层验证、无假设巡检、重复探索、泛采集、知名工具基础用法
|
|
||||||
- 提炼高价值线索:未跟进的发现、待实测工具、可改进产出
|
|
||||||
2. 反思:为什么这些任务低价值?如何设计才能高价值?
|
|
||||||
3. 批判性盘点已有报告和记忆(ls autonomous_reports/ + ../memory),考虑如何发挥更大价值或优化
|
|
||||||
4. 综合以上,产出5-7条TODO写入 `TODO.txt`,TODO已完成内容可压缩丢后面
|
|
||||||
5. 每条格式:`[ ] 类型(产出/冲浪/环境) | 一句话目标 | 验收标准`
|
|
||||||
6. 召唤subagent评审TODO:input仅给TODO列表+"读记忆库自行判断,逐条评分1-10并简述理由"(不喂额外先验信息)
|
|
||||||
7. 读subagent评分,低分项删除或替换
|
|
||||||
8. 立刻**结束**,下次行动再执行
|
|
||||||
|
|
||||||
目标排序(按价值递减):
|
## 执行
|
||||||
1. **实用产出与能力扩展**:写工具解决痛点,在已有能力上解锁新能力(能力树每多一个节点,可能性空间变大)
|
|
||||||
2. **环境发现**:扫描已有但未利用的工具/库/数据源/配置
|
|
||||||
3. **小众工具挖掘**:在GitHub/V2EX/吾爱破解/果核剥壳**等**找冷门实用工具,实测AI常推荐但有坑的方案
|
|
||||||
4. **了解用户与推荐**:分析老代码/PC文件/书签推断偏好,给出个性化推荐(游戏/视频/工具附理由)(低频)
|
|
||||||
5. **自身演进**:思考框架不足,提出改进方案
|
|
||||||
6. **记忆审查**:修正错误或过时记录
|
|
||||||
|
|
||||||
**大型任务**:允许设计**有价值**的大型任务,将其分解成若干个模块或步骤,写入TODO中,每次自主行动执行处理一个模块。
|
**启动**:
|
||||||
|
- update_working_checkpoint: `自主行动|报告→./autonomous_reports/R{XX}_简短描述.md|≤30回合|收尾:重读sop,写报告+更新history+标记TODO`
|
||||||
|
- 读 `./autonomous_reports/history.txt` 推断下一编号RXX + 了解历史避免重复
|
||||||
|
|
||||||
选择原则:个性化优先(只有探测这台PC才能获得的知识)→ 盲区优先(自身参数无法复现,有一定难度)→ 假设驱动(明确要验证什么,边探测边实验)→ 禁止低价值验证(不验证静态配置、不做无假设巡检、不做你轻易完成的工作)
|
**执行**:
|
||||||
|
- ≤30回合,小步快跑,边探测边实验
|
||||||
|
- 用临时脚本验证假设;禁只读即下结论,完整验证再写报告
|
||||||
|
- 即使失败也记录实验过程和结果,失败报告同样有价值
|
||||||
|
- 用户不在线,遇到需要决策的问题写入报告待审,不要卡住
|
||||||
|
|
||||||
探测策略(聚焦原则,非菜单):
|
**收尾(三件事缺一不可)**:
|
||||||
- **线索驱动**:从近期报告中提炼的后续任务,优先于凭空选题
|
1. 写报告 `./autonomous_reports/R{XX}_简短描述.md`,格式简洁仅关键发现详述;若有记忆更新建议,附在报告末尾
|
||||||
- **能力树扩展**:优先能解锁新能力节点的工具/技能(一个节点带来多种可能性)
|
2. 更新 `./autonomous_reports/history.txt`(prepend一条:`RXX | 日期 | 类型 | 主题 | 结论`,严格单行,先读此文件头几行了解格式)
|
||||||
- **个性化优先**:只有探测这台PC/这个用户才能获得的知识 > 通用知识
|
3. 在 `./TODO.txt`(temp根目录)中将已完成条目标记为 `[x]`
|
||||||
- 冲浪规则:每次≤2话题,必须读正文提炼洞察,禁标题搬运;发现好工具→下轮TODO加实测任务
|
|
||||||
|
|
||||||
禁区:❌ Hacker News · 刷新闻头条 · 泛采集标题/无目标刷新闻 · 探索知名工具基础用法 · 调研弱于当前框架的agent · 调研其他web自动化/computer use框架 · 读取自身代码库
|
## 权限边界
|
||||||
|
- 无需批准:只读探测、cwd内写操作/脚本实验
|
||||||
|
- 需写入报告待审:修改 global_mem / memory下SOP、安装软件、外部API调用、删除非临时文件
|
||||||
|
- 绝对禁止:读取密钥、修改核心代码库、不可逆危险操作
|
||||||
|
|
||||||
|
## 等待用户审查
|
||||||
## 执行模式
|
|
||||||
|
|
||||||
⚠️ **监工原则(硬约束)**:主agent在执行模式中**只当监工**,严禁亲自执行任务的实际工作。
|
|
||||||
- ❌ 禁止:主agent自己写脚本跑数据、调API、扫描目录、处理文件等一切「干活」行为
|
|
||||||
- ❌ 禁止:主agent以「为subagent准备数据」为由自己先执行部分工作
|
|
||||||
- ✅ 允许:选任务、写input.txt(任务描述)、启动subagent、轮询监控、质检验收、更新history
|
|
||||||
- 原则:所有实际探测/数据收集/脚本编写/API调用都写进input.txt让subagent去做
|
|
||||||
|
|
||||||
### 执行(有TODO时)
|
|
||||||
0. 从 `TODO.txt` 取**一条**作为当前任务
|
|
||||||
1. update_working_checkpoint: `{选定的当前任务}\n(自主行动时长期保留)subagent任务完成后需重读自主行动sop确定验收流程。每次只执行一个任务!`
|
|
||||||
2. 按 subagent_sop 召唤 subagent,input 需要包含以下全部内容:
|
|
||||||
- **任务**:详细介绍和要求深入执行当前任务 + 验收标准 + 一句话预期收益
|
|
||||||
- **所有实际工作都由subagent完成**:包括数据收集、目录扫描、API调用、脚本编写等,主agent不做任何准备工作
|
|
||||||
- **权限边界**:可执行只读和实验性操作;严禁修改核心记忆/系统设置;严禁读取敏感数据(可检测存在性);控制在30回合内
|
|
||||||
- 无需批准:只读探测、cwd 内写操作/脚本实验
|
|
||||||
- 需要报告:修改 global_mem.txt / memory/ 下 SOP、安装软件、外部 API 调用、删除非临时文件
|
|
||||||
- 绝对禁止:读取密钥、修改核心代码库、不可逆危险操作
|
|
||||||
- **报告要求**:完成后写报告到 `./autonomous_reports/R{XX}_简短描述.md`(XX从history.txt推断),格式简洁仅关键发现详述;
|
|
||||||
- 第一步先将此报告要求update_working_checkpoint进入工作记忆
|
|
||||||
- **行动准则**:边探测边实验,用临时脚本测假设;禁只读即下结论,完整验证再写报告
|
|
||||||
3. 监控 subagent 执行,质量不佳或跑偏可提前终止放弃(监控≠亲自干活)
|
|
||||||
|
|
||||||
### 质检与验收流程
|
|
||||||
4. subagent 完成后,读取报告进行质检:
|
|
||||||
- 报告是否符合格式(标题/分类/内容质量)
|
|
||||||
- 发现不合规可修正报告或回滚操作
|
|
||||||
- 可通过 reply 机制追问 subagent
|
|
||||||
5. 更新 `./autonomous_reports/history.txt`(prepend,先读此文件了解填写格式)
|
|
||||||
- 在 history.txt 首行 prepend 一条:`RXX | 日期 | 类型 | 主题 | 结论`(严格单行)。
|
|
||||||
6. 从 `TODO.txt` 移除已完成条目
|
|
||||||
7. 若报告含记忆更新建议,评估后决定是否采纳;若发现极有价值高质量报告,可在报告文件名上标记。
|
|
||||||
8. 停止,等待下次自主行动
|
|
||||||
|
|
||||||
### 等待用户审查
|
|
||||||
- 用户归来后审查报告,决定批准、修改或拒绝方案
|
- 用户归来后审查报告,决定批准、修改或拒绝方案
|
||||||
2
tgapp.py
2
tgapp.py
@@ -8,7 +8,7 @@ try:
|
|||||||
except:
|
except:
|
||||||
print("Please ask the agent install python-telegram-bot to use telegram module.")
|
print("Please ask the agent install python-telegram-bot to use telegram module.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
from sidercall import mykeys
|
from llmcore import mykeys
|
||||||
|
|
||||||
agent = GeneraticAgent()
|
agent = GeneraticAgent()
|
||||||
agent.verbose = False
|
agent.verbose = False
|
||||||
|
|||||||
Reference in New Issue
Block a user