diff --git a/README.md b/README.md index acb6f717..bda256ad 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ conda env create -f environment.yml # 首次:创建 agentlab 环境并安装 `dev.sh` 自动定位 `agentlab` conda 环境;环境不存在时依 `environment.yml` 创建。 如需使用其他环境名,设置 `AGENTLAB_CONDA_ENV`。 +后端依赖的版本以 `backend/requirements.lock` 为准,装到的是测试跑过的那一套, +不是当天的最新版(见[依赖与锁文件](#依赖与锁文件))。 服务启动于 http://localhost:5273 。 @@ -399,13 +401,36 @@ conda run -n agentlab python -c "import asyncio,microsandbox as m; asyncio.run(m ### 可选依赖 +`environment.yml` 默认已经全部装上。单独补装时带上锁文件,版本才和测过的一致: + ```bash -pip install -e 'backend[docs]' # PDF / Word / PowerPoint / Excel 解析 -pip install -e 'backend[db]' # MySQL / PostgreSQL / Oracle 驱动 -pip install -e 'backend[microvm]' # microVM 沙箱 -pip install -e 'backend[dev]' # pytest +pip install -e 'backend[docs]' -c backend/requirements.lock # PDF / Word / PowerPoint / Excel 解析 +pip install -e 'backend[db]' -c backend/requirements.lock # MySQL / PostgreSQL / Oracle 驱动 +pip install -e 'backend[microvm]' -c backend/requirements.lock # microVM 沙箱 +pip install -e 'backend[dev]' -c backend/requirements.lock # pytest ``` +### 依赖与锁文件 + +`backend/pyproject.toml` 写版本范围,`backend/requirements.lock` 写精确版本:后端全部 +依赖(含间接依赖、全部 extras)锁在测试跑过的那一套上,跨平台通用。`environment.yml` +装包时以它为约束,所以换一台机器装到的也是同一套。 + +LangGraph / LangChain 一族在 `pyproject.toml` 里只放行到下一个小版本:引擎直接依赖 +它们的断点格式、interrupt / resume 和流式事件,这些在小版本里也改过行为。aiosqlite +与 SQLAlchemy 同理——`db/base.py` 给 aiosqlite 打了补丁,连接池断开连接时会走到它。 + +升级依赖要主动做,改完跑一遍测试再提交: + +```bash +./scripts/lock-deps.sh --upgrade-package langgraph # 升一个包(连带它必须跟着动的) +./scripts/lock-deps.sh --upgrade # 全部升到 pyproject 允许的最新 +./scripts/lock-deps.sh # 只加了新依赖:补上它,已锁的不动 +pip install -e 'backend[microvm,dev,db,docs]' -c backend/requirements.lock # 装到当前环境 +``` + +重新生成锁文件需要 [uv](https://docs.astral.sh/uv/);装依赖本身只用 pip。 + ### 数据位置 全部位于 `data/`:`agentlab.db` 业务数据、`checkpoints.db` 执行断点、 diff --git a/backend/pyproject.toml b/backend/pyproject.toml index edf3f9a3..70c6fecc 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -8,18 +8,24 @@ dependencies = [ "uvicorn[standard]>=0.32", "pydantic>=2.9", "pydantic-settings>=2.6", - "sqlalchemy[asyncio]>=2.0.36", - "aiosqlite>=0.20", + # db/base.py 给 aiosqlite 0.22 的 stop() 打了补丁(并发调用会死锁),SQLAlchemy 连接池 + # 强制 terminate 时也会走到它。两个一起卡住小版本,换版本前先确认补丁还成立 + "sqlalchemy[asyncio]>=2.0.36,<2.1", + "aiosqlite>=0.22.1,<0.23", "greenlet>=3.1", "httpx>=0.28", "python-multipart>=0.0.17", - "langgraph", - "langgraph-checkpoint-sqlite", - "langchain-core", - "langchain-anthropic", - "langchain-openai", - "langchain-mcp-adapters", - "mcp", + # 引擎直接依赖这一族的运行时语义:断点格式、interrupt / resume、流式事件、 + # thinking 块。小版本也改过行为(resume 发 Command 在当前版本会直接崩), + # 所以上限卡到下一个小版本——升级要主动改这里、重新锁、跑一遍测试。 + # 精确版本在 requirements.lock 里 + "langgraph>=1.2.11,<1.3", + "langgraph-checkpoint-sqlite>=3.1.1,<3.2", + "langchain-core>=1.6.3,<1.7", + "langchain-anthropic>=1.7.2,<1.8", + "langchain-openai>=1.6.2,<1.7", + "langchain-mcp-adapters>=0.3.2,<0.4", + "mcp>=1.30,<2", "numpy>=2.0", "jsonschema>=4.23", "beautifulsoup4>=4.12", diff --git a/backend/requirements.lock b/backend/requirements.lock new file mode 100644 index 00000000..4e373b5a --- /dev/null +++ b/backend/requirements.lock @@ -0,0 +1,331 @@ +# This file was autogenerated by uv via the following command: +# ./scripts/lock-deps.sh +aiomysql==0.3.2 + # via agentlab-backend (pyproject.toml) +aiosqlite==0.22.1 + # via + # agentlab-backend (pyproject.toml) + # langgraph-checkpoint-sqlite +annotated-doc==0.0.5 + # via fastapi +annotated-types==0.8.0 + # via pydantic +anthropic==1.5.0 + # via langchain-anthropic +anyio==4.15.1 + # via + # anthropic + # httpx + # httpx2 + # langsmith + # mcp + # openai + # sse-starlette + # starlette + # watchfiles +asyncpg==0.31.0 + # via agentlab-backend (pyproject.toml) +attrs==26.1.0 + # via + # jsonschema + # referencing +beautifulsoup4==4.15.0 + # via agentlab-backend (pyproject.toml) +certifi==2026.7.22 + # via + # httpcore + # httpx + # langchain-openai + # requests +cffi==2.1.1 ; platform_python_implementation != 'PyPy' + # via cryptography +charset-normalizer==3.5.1 + # via requests +click==8.5.0 + # via uvicorn +colorama==0.4.6 ; sys_platform == 'win32' + # via pytest +cryptography==50.0.1 + # via + # agentlab-backend (pyproject.toml) + # oracledb + # pyjwt +distro==1.9.0 + # via langsmith +docstring-parser==0.18.0 + # via anthropic +et-xmlfile==2.0.0 + # via openpyxl +fastapi==0.141.1 + # via agentlab-backend (pyproject.toml) +greenlet==3.5.5 + # via + # agentlab-backend (pyproject.toml) + # sqlalchemy +h11==0.16.0 + # via + # httpcore + # httpcore2 + # uvicorn +httpcore==1.0.9 + # via httpx +httpcore2==2.12.0 ; sys_platform != 'emscripten' + # via httpx2 +httptools==0.8.0 + # via uvicorn +httpx==0.28.1 + # via + # agentlab-backend (pyproject.toml) + # langchain-core + # langgraph-sdk + # mcp +httpx-sse==0.4.3 + # via mcp +httpx2==2.12.0 + # via + # anthropic + # langsmith + # openai +httpx2-jsfetch==1.0 ; sys_platform == 'emscripten' + # via httpx2 +idna==3.19 + # via + # anyio + # httpx + # httpx2 + # requests +iniconfig==2.3.0 + # via pytest +jiter==0.17.0 + # via + # anthropic + # openai +jsonpatch==1.33 + # via langchain-core +jsonpointer==3.1.1 + # via jsonpatch +jsonschema==4.26.0 + # via + # agentlab-backend (pyproject.toml) + # mcp +jsonschema-specifications==2025.9.1 + # via jsonschema +langchain-anthropic==1.7.2 + # via agentlab-backend (pyproject.toml) +langchain-core==1.6.3 + # via + # agentlab-backend (pyproject.toml) + # langchain-anthropic + # langchain-mcp-adapters + # langchain-openai + # langgraph + # langgraph-checkpoint + # langgraph-prebuilt + # langgraph-sdk +langchain-mcp-adapters==0.3.2 + # via agentlab-backend (pyproject.toml) +langchain-openai==1.6.2 + # via agentlab-backend (pyproject.toml) +langchain-protocol==0.0.19 + # via + # langchain-core + # langgraph-sdk +langgraph==1.2.11 + # via agentlab-backend (pyproject.toml) +langgraph-checkpoint==4.2.0 + # via + # langgraph + # langgraph-checkpoint-sqlite + # langgraph-prebuilt +langgraph-checkpoint-sqlite==3.1.1 + # via agentlab-backend (pyproject.toml) +langgraph-prebuilt==1.1.0 + # via langgraph +langgraph-sdk==0.4.4 + # via langgraph +langsmith==0.12.4 + # via langchain-core +lxml==6.1.3 + # via + # python-docx + # python-pptx +mcp==1.30.0 + # via + # agentlab-backend (pyproject.toml) + # langchain-mcp-adapters +microsandbox==0.6.18 + # via agentlab-backend (pyproject.toml) +numpy==2.5.3 + # via agentlab-backend (pyproject.toml) +openai==3.13.0 + # via langchain-openai +openpyxl==3.1.5 + # via agentlab-backend (pyproject.toml) +oracledb==26.0.0 + # via agentlab-backend (pyproject.toml) +orjson==3.12.0 + # via + # langgraph-sdk + # langsmith +ormsgpack==1.12.2 + # via langgraph-checkpoint +packaging==26.3 + # via + # langchain-core + # langsmith + # pytest +pillow==12.3.0 + # via python-pptx +pluggy==1.6.0 + # via pytest +pycparser==3.0 ; implementation_name != 'PyPy' and platform_python_implementation != 'PyPy' + # via cffi +pydantic==2.13.5 + # via + # agentlab-backend (pyproject.toml) + # anthropic + # fastapi + # langchain-anthropic + # langchain-core + # langgraph + # langsmith + # mcp + # openai + # pydantic-settings +pydantic-core==2.46.5 + # via pydantic +pydantic-settings==2.15.0 + # via + # agentlab-backend (pyproject.toml) + # mcp +pygments==2.21.0 + # via pytest +pyjwt==2.14.0 + # via mcp +pymysql==1.2.0 + # via aiomysql +pypdf==6.19.0 + # via agentlab-backend (pyproject.toml) +pytest==9.1.1 + # via + # agentlab-backend (pyproject.toml) + # pytest-asyncio +pytest-asyncio==1.4.0 + # via agentlab-backend (pyproject.toml) +python-docx==1.2.0 + # via agentlab-backend (pyproject.toml) +python-dotenv==1.2.3 + # via + # pydantic-settings + # uvicorn +python-multipart==0.0.32 + # via + # agentlab-backend (pyproject.toml) + # mcp +python-pptx==1.0.2 + # via agentlab-backend (pyproject.toml) +pywin32==312 ; sys_platform == 'win32' + # via mcp +pyyaml==6.0.3 + # via + # langchain-core + # uvicorn +referencing==0.37.0 + # via + # jsonschema + # jsonschema-specifications +regex==2026.9.10 + # via tiktoken +requests==2.34.2 + # via + # langsmith + # requests-toolbelt + # tiktoken +requests-toolbelt==1.0.0 + # via langsmith +rpds-py==2026.6.3 + # via + # jsonschema + # referencing +sniffio==1.3.1 + # via + # anthropic + # langsmith + # openai +soupsieve==2.9.2 + # via beautifulsoup4 +sqlalchemy==2.0.52 + # via agentlab-backend (pyproject.toml) +sqlite-vec==0.1.9 + # via langgraph-checkpoint-sqlite +sse-starlette==3.4.11 + # via mcp +starlette==1.6.0 + # via + # fastapi + # mcp + # sse-starlette +tenacity==9.1.4 + # via langchain-core +tiktoken==0.14.0 + # via langchain-openai +truststore==0.10.4 ; sys_platform != 'emscripten' + # via + # httpcore2 + # httpx2 +typing-extensions==4.16.0 + # via + # anthropic + # anyio + # beautifulsoup4 + # fastapi + # httpx2 + # langchain-core + # langchain-mcp-adapters + # langchain-protocol + # langsmith + # mcp + # openai + # oracledb + # pydantic + # pydantic-core + # pytest-asyncio + # python-docx + # python-pptx + # referencing + # sqlalchemy + # starlette + # typing-inspection +typing-inspection==0.4.4 + # via + # fastapi + # mcp + # pydantic + # pydantic-settings +urllib3==2.7.0 + # via requests +uuid-utils==0.17.1 + # via + # langchain-core + # langsmith +uvicorn==0.52.4 + # via + # agentlab-backend (pyproject.toml) + # mcp +uvloop==0.22.1 ; platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32' + # via uvicorn +watchfiles==1.2.0 + # via uvicorn +websockets==16.1.1 + # via + # langgraph-sdk + # langsmith + # uvicorn +xlsxwriter==3.2.9 + # via python-pptx +xxhash==4.0.1 + # via + # langgraph + # langsmith +zstandard==0.25.0 + # via langsmith diff --git a/environment.yml b/environment.yml index 1b0d7198..5d995bdb 100644 --- a/environment.yml +++ b/environment.yml @@ -12,6 +12,9 @@ dependencies: - python=3.12 - pip - pip: + # 版本以锁文件为准:装到的就是测过的那一套,不是当天的最新版。 + # 升级依赖见 scripts/lock-deps.sh + - -c backend/requirements.lock # [microvm] 带上独立内核的沙箱后端(约 35MB wheel,首次运行还要下载 # 约 50MB 运行时,外加一次 OCI 镜像拉取)。不需要就把方括号去掉, # 沙箱会退回 Seatbelt —— 代价是内存限额在 macOS 上限不住。 diff --git a/scripts/lock-deps.sh b/scripts/lock-deps.sh new file mode 100755 index 00000000..91e5e6d4 --- /dev/null +++ b/scripts/lock-deps.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# 重新生成 backend/requirements.lock:后端全部依赖(含间接依赖、全部 extras)的精确版本。 +# +# ./scripts/lock-deps.sh 加了依赖:只补新的,已锁的版本不动 +# ./scripts/lock-deps.sh --upgrade-package langgraph 升一个包(连带它必须跟着动的) +# ./scripts/lock-deps.sh --upgrade 全部升到 pyproject 允许的最新 +# +# 升级之后跑一遍 pytest 和前端检查再提交——锁文件的意义就是"这一套测过"。 +# 锁是跨平台的(--universal),Linux / Windows 上装到的也是同一套版本。 +# 需要 uv(brew install uv);装包慢可以在命令前加 UV_INDEX_URL=<镜像地址>。 +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +command -v uv >/dev/null || { echo "缺少 uv:https://docs.astral.sh/uv/"; exit 1; } + +cd "$ROOT/backend" +uv pip compile pyproject.toml \ + --all-extras \ + --universal \ + --python-version 3.12 \ + --custom-compile-command "./scripts/lock-deps.sh" \ + -o requirements.lock \ + "$@"