add uv install guide & pyproject.toml; unify error prefix to !!!Error:
This commit is contained in:
28
README.md
28
README.md
@@ -89,6 +89,20 @@ cp mykey_template.py mykey.py
|
||||
python launch.pyw
|
||||
```
|
||||
|
||||
#### Method 2: uv (for experienced Python users)
|
||||
|
||||
If you prefer a modern Python workflow, GenericAgent also provides a minimal `pyproject.toml`:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/lsdefine/GenericAgent.git
|
||||
cd GenericAgent
|
||||
uv pip install -e ".[ui]" # Core + GUI dependencies
|
||||
cp mykey_template.py mykey.py
|
||||
python launch.pyw
|
||||
```
|
||||
|
||||
> GenericAgent is meant to grow its environment through the Agent itself, not by pre-installing every possible package.
|
||||
|
||||
Full guide: [GETTING_STARTED.md](GETTING_STARTED.md)
|
||||
|
||||
---
|
||||
@@ -293,6 +307,20 @@ cp mykey_template.py mykey.py
|
||||
python launch.pyw
|
||||
```
|
||||
|
||||
#### 方法二:uv 快速安装(熟悉 Python 的用户)
|
||||
|
||||
如果你习惯现代 Python 工作流,GenericAgent 也提供了一个最小化的 `pyproject.toml`:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/lsdefine/GenericAgent.git
|
||||
cd GenericAgent
|
||||
uv pip install -e ".[ui]" # 核心 + GUI 依赖
|
||||
cp mykey_template.py mykey.py
|
||||
python launch.pyw
|
||||
```
|
||||
|
||||
> GenericAgent 更推荐由 Agent 在使用中自举环境,而不是预先手动装完整依赖。
|
||||
|
||||
完整引导流程见 [GETTING_STARTED.md](GETTING_STARTED.md)。
|
||||
|
||||
📖 新手使用指南(图文版):[飞书文档](https://my.feishu.cn/wiki/CGrDw0T76iNFuskmwxdcWrpinPb)
|
||||
|
||||
14
llmcore.py
14
llmcore.py
@@ -148,7 +148,7 @@ def _parse_claude_sse(resp_lines):
|
||||
elif evt_type == "error":
|
||||
err = evt.get("error", {})
|
||||
emsg = err.get("message", str(err)) if isinstance(err, dict) else str(err)
|
||||
warn = f"\n\n[SSE Error: {emsg}]"; break
|
||||
warn = f"\n\n!!!Error: SSE {emsg}"; break
|
||||
if not warn:
|
||||
if not got_message_stop and not stop_reason: warn = "\n\n[!!! 流异常中断,未收到完整响应 !!!]"
|
||||
elif stop_reason == "max_tokens": warn = "\n\n[!!! Response truncated: max_tokens !!!]"
|
||||
@@ -211,7 +211,7 @@ def _parse_openai_sse(resp_lines, api_mode="chat_completions"):
|
||||
elif etype == "error":
|
||||
err = evt.get("error", {})
|
||||
emsg = err.get("message", str(err)) if isinstance(err, dict) else str(err)
|
||||
if emsg: content_text += f"Error: {emsg}"; yield f"Error: {emsg}"
|
||||
if emsg: content_text += f"!!!Error: {emsg}"; yield f"!!!Error: {emsg}"
|
||||
break
|
||||
elif etype == "response.completed":
|
||||
usage = evt.get("response", {}).get("usage", {})
|
||||
@@ -522,7 +522,7 @@ class BaseSession:
|
||||
if block.get('type', '') == 'tool_use':
|
||||
tu = {'name': block.get('name', ''), 'arguments': block.get('input', {})}
|
||||
yield f'<tool_use>{json.dumps(tu, ensure_ascii=False)}</tool_use>'
|
||||
if not content.startswith("Error:"): self.history.append({"role": "assistant", "content": [{"type": "text", "text": content}]})
|
||||
if not content.startswith("!!!Error:"): self.history.append({"role": "assistant", "content": [{"type": "text", "text": content}]})
|
||||
return _ask_gen() if stream else ''.join(list(_ask_gen()))
|
||||
|
||||
class ClaudeSession(BaseSession):
|
||||
@@ -537,7 +537,7 @@ class ClaudeSession(BaseSession):
|
||||
if r.status_code != 200: raise Exception(f"HTTP {r.status_code} {r.content.decode('utf-8', errors='replace')[:500]}")
|
||||
return (yield from _parse_claude_sse(r.iter_lines())) or []
|
||||
except Exception as e:
|
||||
yield (err := f"Error: {e}")
|
||||
yield (err := f"!!!Error: {e}")
|
||||
return [{"type": "text", "text": err}]
|
||||
def make_messages(self, raw_list):
|
||||
msgs = [{"role": m['role'], "content": list(m['content'])} for m in raw_list]
|
||||
@@ -621,7 +621,7 @@ class NativeClaudeSession(BaseSession):
|
||||
elif b.get("type") == "thinking": yield ""
|
||||
return content_blocks
|
||||
except Exception as e:
|
||||
yield (err := f"Error: {e}")
|
||||
yield (err := f"!!!Error: {e}")
|
||||
return [{"type": "text", "text": err}]
|
||||
|
||||
def ask(self, msg):
|
||||
@@ -635,7 +635,7 @@ class NativeClaudeSession(BaseSession):
|
||||
try:
|
||||
while True: yield next(gen)
|
||||
except StopIteration as e: content_blocks = e.value or []
|
||||
if content_blocks and not (len(content_blocks) == 1 and content_blocks[0].get("text", "").startswith("Error:")):
|
||||
if content_blocks and not (len(content_blocks) == 1 and content_blocks[0].get("text", "").startswith("!!!Error:")):
|
||||
self.history.append({"role": "assistant", "content": content_blocks})
|
||||
text_parts = [b["text"] for b in content_blocks if b.get("type") == "text"]
|
||||
content = "\n".join(text_parts).strip()
|
||||
@@ -891,7 +891,7 @@ class MixinSession:
|
||||
return self._cur_idx
|
||||
def _raw_ask(self, *args, **kwargs):
|
||||
base, n = self._pick(), len(self._sessions)
|
||||
test_error = lambda x: isinstance(x, str) and (x.startswith('Error:') or x.startswith('[Error:'))
|
||||
test_error = lambda x: isinstance(x, str) and x.lstrip().startswith(('!!!Error:', '[Error:'))
|
||||
for attempt in range(self._retries + 1):
|
||||
idx = (base + attempt) % n
|
||||
gen = self._orig_raw_asks[idx](*args, **kwargs)
|
||||
|
||||
40
pyproject.toml
Normal file
40
pyproject.toml
Normal file
@@ -0,0 +1,40 @@
|
||||
# AI install hint: choose deps by OS/env + needed ui/bot. do NOT install all.
|
||||
# minimal core first; missing packages can be installed on demand.
|
||||
|
||||
[project]
|
||||
name = "genericagent"
|
||||
version = "0.1.0"
|
||||
description = "Minimalist self-evolving autonomous agent framework"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10,<3.14"
|
||||
license = { text = "MIT" }
|
||||
dependencies = [
|
||||
"requests>=2.28",
|
||||
"beautifulsoup4>=4.12",
|
||||
"bottle>=0.12",
|
||||
"simple-websocket-server>=0.4",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
# select extras, not all. match current task/env.
|
||||
# examples: .[ui] for GUI, bot deps only if bot needed.
|
||||
ui = [
|
||||
"streamlit>=1.28",
|
||||
"pywebview>=4.0",
|
||||
]
|
||||
all-frontends = [
|
||||
"python-telegram-bot>=20.0",
|
||||
"qq-botpy>=1.0",
|
||||
"pycryptodome>=3.19",
|
||||
"qrcode>=7.4",
|
||||
"lark-oapi>=1.0",
|
||||
"wecom-aibot-sdk>=1.0",
|
||||
"dingtalk-stream>=1.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools>=68.0"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.setuptools]
|
||||
py-modules = []
|
||||
Reference in New Issue
Block a user