improve: fallback search, history compression refactor, tg bot stability
This commit is contained in:
19
ga.py
19
ga.py
@@ -103,8 +103,8 @@ def first_init_driver():
|
||||
if len(sess) > 0: break
|
||||
if len(sess) == 0: return
|
||||
if len(sess) == 1:
|
||||
driver.newtab()
|
||||
time.sleep(5)
|
||||
#driver.newtab()
|
||||
time.sleep(3)
|
||||
|
||||
def web_scan(tabs_only=False, switch_tab_id=None):
|
||||
"""
|
||||
@@ -207,7 +207,8 @@ def file_read(path, start=1, keyword=None, count=200, show_linenos=True):
|
||||
res = list(before) + [(i, l)] + list(itertools.islice(stream, count - len(before) - 1))
|
||||
break
|
||||
before.append((i, l))
|
||||
else: return f"Keyword '{keyword}' not found after line {start}."
|
||||
else: return f"Keyword '{keyword}' not found after line {start}. Falling back to content from line {start}:\n\n" \
|
||||
+ file_read(path, start, None, count, show_linenos)
|
||||
else: res = itertools.islice(stream, count)
|
||||
return "\n".join(f"{i}|{l}" if show_linenos else l for i, l in res)
|
||||
except Exception as e:
|
||||
@@ -287,8 +288,9 @@ class GenericAgentHandler(BaseHandler):
|
||||
result = web_scan(tabs_only=tabs_only, switch_tab_id=switch_tab_id)
|
||||
content = result.pop("content", None)
|
||||
yield f'[Info] {str(result)}\n'
|
||||
if content: next_prompt = f"```html\n{content}\n```"
|
||||
if content: next_prompt = f"<tool_result>\n```html\n{content}\n```\n</tool_result>"
|
||||
else: next_prompt = "标签页列表如上\n"
|
||||
# 手动tool_result为了触发历史上下文自动压缩
|
||||
return StepOutcome(result, next_prompt=next_prompt)
|
||||
|
||||
def do_web_execute_js(self, args, response):
|
||||
@@ -296,15 +298,16 @@ class GenericAgentHandler(BaseHandler):
|
||||
支持将结果保存到文件供后续读取分析,但保存功能仅限即时读取,与await等异步操作不兼容。
|
||||
'''
|
||||
script = args.get("script", "")
|
||||
if not script: return StepOutcome(None, next_prompt="[Error] Empty script param. Check your tool call arguments.")
|
||||
save_to_file = args.get("save_to_file", "")
|
||||
result = web_execute_js(script)
|
||||
if save_to_file and "js_return" in result:
|
||||
content = str(result["js_return"] or '')
|
||||
abs_path = self._get_abs_path(save_to_file)
|
||||
result["js_return"] = content[:200] + ("..." if len(content) > 200 else "")
|
||||
result["js_return"] = smart_format(content, max_str_len=200)
|
||||
try:
|
||||
with open(abs_path, 'w', encoding='utf-8') as f: f.write(str(content))
|
||||
result["js_return"] += f"\n\n[已保存以上内容到 {abs_path}]"
|
||||
result["js_return"] += f"\n\n[已保存完整内容到 {abs_path}]"
|
||||
except:
|
||||
result['js_return'] += f"\n\n[保存失败,无法写入文件 {abs_path}]"
|
||||
print("Web Execute JS Result:", smart_format(result))
|
||||
@@ -371,13 +374,15 @@ class GenericAgentHandler(BaseHandler):
|
||||
if show_linenos:
|
||||
tips = '由于设置了show_linenos,以下返回信息为:(行号|)内容 。\n'
|
||||
result = tips + result
|
||||
if ' ... [TRUNCATED]' in result:
|
||||
result += '\n\n(某些行被截断,如需完整内容可改用 code_run 读取)'
|
||||
next_prompt = self._get_anchor_prompt()
|
||||
if 'memory' in path or 'sop' in path:
|
||||
next_prompt += "\nPROTOCOL: 你正在读取记忆或SOP文件,若决定按sop执行请先调用相关工具提取sop中的关键点(特别是靠后的)进入工作记忆。"
|
||||
return StepOutcome(result, next_prompt=next_prompt)
|
||||
|
||||
def do_update_working_mem(self, args, response):
|
||||
'''读取完sop后,为整个任务设定后续需要临时记忆的重点。
|
||||
'''为整个任务设定后续需要临时记忆的重点。
|
||||
'''
|
||||
key_info = args.get("key_info", "")
|
||||
related_sop = args.get("related_sop", "")
|
||||
|
||||
33
sidercall.py
33
sidercall.py
@@ -13,6 +13,19 @@ google_api_key = mykeys.get("google_api_key")
|
||||
proxy = mykeys.get("proxy", 'http://127.0.0.1:2082')
|
||||
proxies = {"http": proxy, "https": proxy} if proxy else None
|
||||
|
||||
def compress_history_tags(messages, keep_recent=4, max_len=200):
|
||||
"""Compress <thinking>/<tool_use>/<tool_result> tags in older messages to save tokens."""
|
||||
for i, msg in enumerate(messages):
|
||||
if i < len(messages) - keep_recent and 'orig' not in msg:
|
||||
msg['orig'] = msg['prompt']
|
||||
for tag in ('thinking', 'tool_use', 'tool_result'):
|
||||
msg['prompt'] = re.sub(
|
||||
rf'(<{tag}>)([\s\S]*?)(</{tag}>)',
|
||||
lambda m, _ml=max_len: m.group(1) + (m.group(2)[:_ml] + '...') + m.group(3) if len(m.group(2)) > _ml else m.group(0),
|
||||
msg['prompt']
|
||||
)
|
||||
return messages
|
||||
|
||||
class SiderLLMSession:
|
||||
def __init__(self, default_model="gemini-3.0-flash"):
|
||||
from sider_ai_api import Session
|
||||
@@ -32,16 +45,7 @@ class ClaudeSession:
|
||||
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()
|
||||
def _trim_messages(self, messages):
|
||||
# 压缩4轮前的assistant消息:truncate <thinking>/<tool_use> 块
|
||||
for i, msg in enumerate(messages):
|
||||
if i < len(messages) - 4 and 'orig' not in msg:
|
||||
msg['orig'] = msg['prompt']
|
||||
for tag in ('thinking', 'tool_use', 'tool_result'):
|
||||
msg['prompt'] = re.sub(
|
||||
rf'(<{tag}>)([\s\S]*?)(</{tag}>)',
|
||||
lambda m: m.group(1) + (m.group(2)[:200] + '...') + m.group(3) if len(m.group(2)) > 200 else m.group(0),
|
||||
msg['prompt']
|
||||
)
|
||||
compress_history_tags(messages)
|
||||
total = sum(len(m['prompt']) for m in messages)
|
||||
if total <= self.context_win * 4: return messages
|
||||
target, current, result = self.context_win * 4 * 0.9, 0, []
|
||||
@@ -120,16 +124,9 @@ class LLMSession:
|
||||
yield f"Error: {str(e)}"
|
||||
|
||||
def make_messages(self, raw_list, omit_images=True):
|
||||
compress_history_tags(raw_list)
|
||||
messages = []
|
||||
for i, msg in enumerate(raw_list):
|
||||
if i < len(raw_list) - 4 and 'orig' not in msg:
|
||||
msg['orig'] = msg['prompt']
|
||||
for tag in ('thinking', 'tool_use', 'tool_result'):
|
||||
msg['prompt'] = re.sub(
|
||||
rf'(<{tag}>)([\s\S]*?)(</{tag}>)',
|
||||
lambda m: m.group(1) + (m.group(2)[:200] + '...') + m.group(3) if len(m.group(2)) > 200 else m.group(0),
|
||||
msg['prompt']
|
||||
)
|
||||
prompt = msg['prompt']
|
||||
if omit_images and msg['image']: messages.append({"role": msg['role'], "content": "[Image omitted, if you needed it, ask me]\n" + prompt})
|
||||
elif not omit_images and msg['image']:
|
||||
|
||||
20
tgapp.py
20
tgapp.py
@@ -3,6 +3,7 @@ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
from agentmain import GeneraticAgent
|
||||
from telegram import Update
|
||||
from telegram.ext import ApplicationBuilder, MessageHandler, CommandHandler, filters, ContextTypes
|
||||
from telegram.request import HTTPXRequest
|
||||
import mykey
|
||||
|
||||
agent = GeneraticAgent()
|
||||
@@ -92,17 +93,32 @@ if __name__ == '__main__':
|
||||
if not ALLOWED: sys.exit('ERROR: tg_allowed_users in mykey.py is empty or missing. Set it to avoid unauthorized access.')
|
||||
_logf = open(os.path.join(os.path.dirname(__file__), 'temp', 'tgapp.log'), 'a', encoding='utf-8', buffering=1)
|
||||
sys.stdout = sys.stderr = _logf
|
||||
print('[NEW] New process starting, the above are history infos ...')
|
||||
threading.Thread(target=agent.run, daemon=True).start()
|
||||
proxy = vars(mykey).get('proxy', 'http://127.0.0.1:2082')
|
||||
print('proxy:', proxy)
|
||||
app = ApplicationBuilder().token(mykey.tg_bot_token).proxy(proxy).get_updates_proxy(proxy).build()
|
||||
request = HTTPXRequest(proxy=proxy, read_timeout=30, write_timeout=30, connect_timeout=30, pool_timeout=30)
|
||||
app = (ApplicationBuilder()
|
||||
.token(mykey.tg_bot_token)
|
||||
.request(request)
|
||||
.get_updates_request(request)
|
||||
.build())
|
||||
app.add_handler(CommandHandler("stop", cmd_abort))
|
||||
app.add_handler(CommandHandler("llm", cmd_llm))
|
||||
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_msg))
|
||||
|
||||
async def _error_handler(update, context: ContextTypes.DEFAULT_TYPE):
|
||||
print(f"[{time.strftime('%m-%d %H:%M')}] TG error: {context.error}", flush=True)
|
||||
app.add_error_handler(_error_handler)
|
||||
|
||||
print(f"TG bot starting... {time.strftime('%m-%d %H:%M')}")
|
||||
while True:
|
||||
try:
|
||||
app.run_polling(drop_pending_updates=True)
|
||||
app.run_polling(
|
||||
drop_pending_updates=True,
|
||||
poll_interval=1.0,
|
||||
timeout=30,
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"[{time.strftime('%m-%d %H:%M')}] polling crashed: {e}", flush=True)
|
||||
time.sleep(10)
|
||||
|
||||
Reference in New Issue
Block a user