fix(sandbox): docker 下 system prompt / SKILL 文档统一用容器路径
docker backend 下 shell/run_python/fs 工具全在容器里跑(<workspace>/users/<uid> bind 到 /workspace),但喂给 LLM 的路径多处仍是宿主绝对路径(容器内不存在), agent 据此 find 全空、瞎转到 pwd 才发现真身在 /workspace/<wd>。 - core/agent_builder.py::_build_system_prompt:docker 下 task_dir + 「宪法」 glob 范例换成容器路径 /workspace/<wd>,去掉容器里无意义的 cwd 行(cwd 恒等 task_dir);host 不变。修法同 LoadSkillTool 的 container_skills_dir 改写。 - skills 文档同类宿主路径残留清扫:patent 跨 skill 调 proposal 脚本由 <repo_root>/...(硬编码 D:/projects/zcbot)改兄弟相对 <skill_dir>/../proposal/...; research fetch_pdf 范例硬编码 D:/... 改 <task_dir> 占位;patent/proposal/ppt 的 <task_dir> 举例的废弃旧布局 workspace/tasks/<task_id> 改 host/docker 双形态说明。 - ppt 图标缓存写进只读挂载修复(方案 A):种子图标库 <skill_dir>/assets/icons/ 降为只读(glob 读),fetch_icon.py 新拉图标一律 -o <task_dir>/assets/icons/, 读路径改种子库 + 本 task 两处都 glob。docker 下 skills 是 :ro bind,旧写法必败; host 下还顺带污染仓库工作树。脚本已 out.parent.mkdir,无需改。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9a1e88d86f
commit
7b09c77f76
|
|
@ -23,6 +23,9 @@
|
|||
|
||||
### 2026-06-03
|
||||
|
||||
- **修 docker sandbox 下 system prompt 焊死宿主路径(agent 找不到自己的文件)**:`ZCBOT_SANDBOX_BACKEND=docker` 时 shell/run_python/fs 工具全在容器里跑(`<workspace>/users/<uid>` bind 到 `/workspace`),但 `_build_system_prompt` 注入的 `task_dir` / cwd 是宿主绝对路径(容器内不存在),LLM 据此 `find /home/ubuntu/zcbot ...` 全空、瞎转到 `pwd` 才发现真身在 `/workspace/<wd>`。修法同 `LoadSkillTool` 的 `container_skills_dir` 改写:docker 下 `task_dir` + 「宪法」glob 范例换成容器路径 `/workspace/<wd_rel>`,并去掉 docker 下无意义的 cwd 行(容器 cwd 恒等 task_dir);host 不变。
|
||||
- **顺扫清掉 SKILL.md 里残留的宿主路径假设(同 docker 隐患)**:`patent` 跨 skill 调 proposal 脚本原用 `<repo_root>/skills/proposal/...`(还举例硬编码 `D:/projects/zcbot`)→ 改兄弟 skill 相对 `<skill_dir>/../proposal/scripts/...`(两后端都对);`research` 的 `fetch_pdf` 范例硬编码 `working_dir=r"D:/..."` → 改 `<task_dir>` 占位;`patent`/`proposal`/`ppt` 的 `<task_dir>` 举例用废弃旧布局 `…/workspace/tasks/<task_id>/` → 改 host/docker 双形态说明。
|
||||
- **修 ppt 图标缓存写进只读挂载(docker 拉新图标失败)**:`fetch_icon.py -o <skill_dir>/assets/icons/` 在 docker 下 skills 是 `:ro` bind,写回必败;host 下还顺带污染仓库工作树。改为(方案 A,与"产物只写 task_dir"的全局规矩一致):种子图标库 `<skill_dir>/assets/icons/` 降为**只读**(glob 读),`fetch_icon.py` 新拉的图标一律 `-o <task_dir>/assets/icons/`;读路径改两处都 glob(种子库 + 本 task)。涉 `ppt/SKILL.md`、`references/icons.md`、`assets/icons/INDEX.md`;脚本本身已 `out.parent.mkdir`,无需改。
|
||||
- **默认镜像源改清华(pip+apt)/ 腾讯(npm)**:腾讯 PyPI 吐损坏 litellm wheel(index 声明 sha256 与文件实际字节不符,非篡改 = 镜像端文件损坏)。`deploy/update.sh` 三默认值改清华(境内稳 + 同步及时;npm 无清华源走腾讯);换默认让下次 build pip 层全量重跑一次。
|
||||
- **回退 `ZCBOT_WORKSPACE_DIR` env 覆盖,workspace 落数据盘改用 bind mount**:env 覆盖与 `core/paths.py` 锚 ROOT 的相对存储冲突 —— env 指向 ROOT 外致文件面板 / agent resume / 新建 task 三家分叉。`resolve_workspace` 回退成 `arg > cfg > 默`(均 ROOT 内),数据盘改用 bind mount(`/data/zcbot/workspace` → `ROOT/workspace`,DB 不改、dev 不受影响)。
|
||||
|
||||
|
|
|
|||
|
|
@ -212,7 +212,22 @@ def _build_system_prompt(
|
|||
if skills.skills:
|
||||
prompt += f"\n\n## 可用 skill (用 load_skill 加载完整指引)\n{skills.discovery_block()}"
|
||||
prompt += memory_block(workspace_dir, user_id)
|
||||
# docker backend 下 shell/run_python/fs 工具全在容器里跑,容器把
|
||||
# `<workspace>/users/<uid>` bind 到 `/workspace`、`--workdir /workspace/<wd>`
|
||||
# (executor_docker.py:99-100)。此时 prompt 必须给**容器路径**,否则 LLM
|
||||
# 拿着宿主绝对路径在沙盒里 find 不到任何东西(host 路径容器内根本不存在)。
|
||||
# host backend 不变,直接用宿主绝对路径。
|
||||
wd_abs = working_dir.resolve()
|
||||
is_docker = os.getenv("ZCBOT_SANDBOX_BACKEND", "host").lower() == "docker"
|
||||
if is_docker:
|
||||
try:
|
||||
wd_rel = wd_abs.relative_to(user_root(workspace_dir, user_id))
|
||||
wd_path = "/workspace/" + wd_rel.as_posix()
|
||||
except ValueError:
|
||||
# working_dir 不在 user_root 下 —— 防御性兜底,正常路径不会到这里
|
||||
wd_path = "/workspace"
|
||||
else:
|
||||
wd_path = str(wd_abs)
|
||||
today = datetime.now().strftime("%Y-%m-%d")
|
||||
tname = task_name or "<未指定>"
|
||||
short_id = task_id.hex[:8]
|
||||
|
|
@ -220,10 +235,21 @@ def _build_system_prompt(
|
|||
f"- **task 预选 skill**: `{task_skill}` — 用户创建时声明的主 skill\n"
|
||||
if task_skill else ""
|
||||
)
|
||||
# docker 下容器 cwd 恒等于 task_dir(fs 工具 base_dir = --workdir = task_dir),
|
||||
# 不存在"另一个只读宿主 cwd",留 cwd 行只会误导 → 去掉,改提一句工具起步点。
|
||||
if is_docker:
|
||||
loc_lines = (
|
||||
f"- **task_dir(工作目录,所有产物写这里;shell / run_python / 读写工具"
|
||||
f"均从此目录起步,相对路径都相对它)**: `{wd_path}`\n"
|
||||
)
|
||||
else:
|
||||
loc_lines = (
|
||||
f"- cwd(用户启动时所在目录,只读用): `{tool_base}`\n"
|
||||
f"- **task_dir(所有产物写到这里)**: `{wd_path}`\n"
|
||||
)
|
||||
prompt += (
|
||||
f"\n\n## 工作目录与 task 上下文\n"
|
||||
f"- cwd(用户启动时所在目录,只读用): `{tool_base}`\n"
|
||||
f"- **task_dir(所有产物写到这里)**: `{wd_abs}`\n"
|
||||
f"{loc_lines}"
|
||||
f"- **task_short_id**(永不变,「宪法」文件主锚): `{short_id}`\n"
|
||||
f"- **task_name**(可变,写进文件名作人类可读说明): `{tname}`\n"
|
||||
f"- **today**(当前日期,用于「宪法」文件命名): `{today}`\n"
|
||||
|
|
@ -243,7 +269,7 @@ def _build_system_prompt(
|
|||
f"`<task_name>` = `{tname}`(可变,人类可读说明,原样用 含 CJK / 空格);"
|
||||
f"`<base>` 由 skill 定义(如 proposal/ppt 的 `spec`)。\n\n"
|
||||
f"**取 current 版本规则**:read 时 **按 task_short_id 锚定** glob "
|
||||
f"`{wd_abs}/*-{short_id}-*.<base>.md` → 按文件名字典序排 → 取最大者"
|
||||
f"`{wd_path}/*-{short_id}-*.<base>.md` → 按文件名字典序排 → 取最大者"
|
||||
f"(= 最新日期)。这样即使用户改了 task_name,旧文件仍能定位(`<task_name>` "
|
||||
f"那段视为「建时快照」,不强求同步)。这是「current 指针」的纯文件名实现,"
|
||||
f"agent 自己拼即可。\n\n"
|
||||
|
|
|
|||
|
|
@ -128,19 +128,19 @@ read <skill_dir>/references/self_check.md
|
|||
# 模型按清单 6 类逐项过一遍 sections/*.md, 不过则回头 edit
|
||||
|
||||
# 2. mermaid 附图预渲染 (章节有 ```mermaid``` 块就跑)
|
||||
python <repo_root>/skills/proposal/scripts/render_diagrams.py <task_dir>/sections/
|
||||
python <skill_dir>/../proposal/scripts/render_diagrams.py <task_dir>/sections/
|
||||
|
||||
# 3. 渲染 .docx (复用 proposal skill 的脚本,patent 不另写)
|
||||
python <repo_root>/skills/proposal/scripts/render_docx.py <task_dir>/sections/ --fund-type key_rd -o <task_dir>/<案件名>_技术交底书.docx
|
||||
python <skill_dir>/../proposal/scripts/render_docx.py <task_dir>/sections/ --fund-type key_rd -o <task_dir>/<案件名>_技术交底书.docx
|
||||
```
|
||||
|
||||
> `render_docx.py` 的 `--fund-type` 只影响目录页表头文案与封面,不影响章节解析 —— 交底书复用 `key_rd` 排版规范(国标黑体/宋体/1.5 倍行距)。封面页用户拿到后手动改成"技术交底书"标题,或在 sections/00_封面.md 自定义。
|
||||
|
||||
`<repo_root>` 取自 `<skill_dir>` 的父级再父级,e.g. `skill_dir = D:/projects/zcbot/skills/patent` → `repo_root = D:/projects/zcbot`。
|
||||
复用的 proposal 脚本是 patent 的**兄弟 skill**,用 `<skill_dir>/../proposal/scripts/...` 定位(`<skill_dir>` = load_skill 头部给的本 skill 绝对目录,host 下是宿主路径、docker 沙盒里是 `/sandbox/skills/patent`,`../proposal` 在两种后端都落到同级 proposal 目录)。**不要**拼 repo 根的宿主绝对路径 —— docker 容器里看不到宿主路径。
|
||||
|
||||
## 工作目录
|
||||
|
||||
`<task_dir>` = system prompt 给的**绝对路径**(`…/workspace/tasks/<task_id>/`)。**所有产物都写到 task_dir 下**,不要写到 cwd / `skills/` / repo 根。
|
||||
`<task_dir>` = system prompt 给的**绝对路径**(host 下形如 `…/workspace/users/<uid>/<wd>/`,docker 沙盒里是 `/workspace/<wd>/`)。**所有产物都写到 task_dir 下**,不要写到 cwd / `skills/` / repo 根。
|
||||
|
||||
```
|
||||
<task_dir>/
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ description: 生成 PowerPoint 演示文稿 (.pptx) 文件。✅ 触发:用户
|
|||
- `references/design_principles.md` —— 画布尺寸 + 字号/配色/留白/字数预算等硬规则
|
||||
- `references/layouts.md` —— 9 种版式的 python-pptx 起手代码 + 安全区/越界保护 + `apply_brand` 品牌条
|
||||
- `references/icons.md` —— 业务图标两层:Iconify (在线/本地缓存) / unicode 字形兜底
|
||||
- `assets/icons/` —— 本地图标缓存 (Iconify 拉过的图存这,见 `INDEX.md` 推荐清单)
|
||||
- `assets/icons/` —— **只读**种子图标库 (skill 自带的商务红 tabler 集,见 `INDEX.md`;docker 沙盒里 skills 是只读挂载。新拉的图标写 `<task_dir>/assets/icons/`)
|
||||
- 素材摄取: 用 `markitdown` CLI 把 PDF/DOCX/PPTX/XLSX/HTML/URL 转干净 Markdown,统一落到 `<task_dir>/source/<name>.md`(同 working_dir 多 task 共享 source 池)
|
||||
- `scripts/fetch_icon.py` —— 从 Iconify CDN 拉 SVG/PNG (染主题色,缓存本地)
|
||||
- `scripts/fetch_icon.py` —— 从 Iconify CDN 拉 SVG/PNG (染主题色,缓存到 `<task_dir>/assets/icons/`)
|
||||
- `scripts/render_icon.py` —— unicode 字形 → 透明 PNG (Iconify 没有时兜底)
|
||||
- `scripts/quality_check.py` —— 产物 .pptx 验收 (越界 / 文本溢出 / 颜色一致)
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ glob <task_dir>/*-<task_short_id>-*.spec.md → 按文件名字典序排,取最
|
|||
| 4 | 风格 | **现代简约** (白底 + 细线 + 留白) |
|
||||
| 5 | 配色 | **商务红** `#C00000` `#E15554` `#FFC107` (见上"默认主题") |
|
||||
| 6 | 字体 | **微软雅黑 + Arial** |
|
||||
| 7 | 图标 | **Iconify `tabler` 集** (描边商务图标,主色染色;`fetch_icon.py` 拉到 `assets/icons/` 缓存) |
|
||||
| 7 | 图标 | **Iconify `tabler` 集** (描边商务图标,主色染色;`fetch_icon.py` 拉到 `<task_dir>/assets/icons/`) |
|
||||
| 8 | 图表 | 数据 ≥ 3 个点的页用 matplotlib 配图 |
|
||||
|
||||
把这 8 项写进上面那个 task 级 spec 文件,以表格形式给用户预览,问一句"按这个开干?"。**spec 写定后不再改**(要改就走 §0 的「重定调」分支,以 today 为前缀写新版,旧版保留)。
|
||||
|
|
@ -74,7 +74,7 @@ glob <task_dir>/*-<task_short_id>-*.spec.md → 按文件名字典序排,取最
|
|||
|
||||
每页流程:
|
||||
1. 读 current spec(即使刚读过)
|
||||
2. **图标先于版式**: 这一页要用什么概念图标? 先 `glob <skill_dir>/assets/icons/` 看本地有没有 (`<skill_dir>` 是 `load_skill` 头里的绝对路径),没有就 `python <skill_dir>/scripts/fetch_icon.py <name> --set tabler --color C00000 --size 128 -o <skill_dir>/assets/icons/...` 拉一个;`add_picture` 嵌入。**几何形状(圆点/徽章/装饰线)不算图标,走 layouts.md helper 即可**
|
||||
2. **图标先于版式**: 这一页要用什么概念图标? 先 `glob` 两处看有没有现成 —— 种子库 `<skill_dir>/assets/icons/`(只读,`<skill_dir>` 是 `load_skill` 头里的绝对路径)+ 本 task `<task_dir>/assets/icons/`;没有就 `python <skill_dir>/scripts/fetch_icon.py <name> --set tabler --color C00000 --size 128 -o <task_dir>/assets/icons/...` 拉一个(种子库只读,新图标落 task 目录);`add_picture` 嵌入。**几何形状(圆点/徽章/装饰线)不算图标,走 layouts.md helper 即可**
|
||||
3. 写一个 `run_python` block,用 python-pptx 添加这一页 (载入已有 .pptx → append slide → save)
|
||||
4. 报这一页:版式、标题、要点条数、用了哪些图标
|
||||
5. 用户确认 / 微调后再下一页
|
||||
|
|
@ -107,7 +107,7 @@ python <skill_dir>/scripts/quality_check.py <task_dir>/<output.pptx> --spec <tas
|
|||
|
||||
## 工作目录约定
|
||||
|
||||
下文 `<task_dir>` = system prompt 里「task_dir」给的**绝对路径**(形如 `…/workspace/tasks/<task_id>/`)。**所有产物都写到 task_dir 下**,不要写到 cwd / `skills/` / repo 根;`assets/icons/` 是 skill 自带的图标缓存,继续走 `skills/ppt/assets/icons/`。
|
||||
下文 `<task_dir>` = system prompt 里「task_dir」给的**绝对路径**(host 下形如 `…/workspace/users/<uid>/<wd>/`,docker 沙盒里是 `/workspace/<wd>/`)。**所有产物都写到 task_dir 下**,不要写到 cwd / `skills/` / repo 根;图标分两处:skill 自带的**只读种子库**走 `<skill_dir>/assets/icons/`(docker 沙盒里 skills 只读,只读不写),`fetch_icon.py` 新拉的图标写 `<task_dir>/assets/icons/`(详见 references/icons.md §A)。
|
||||
|
||||
```
|
||||
<task_dir>/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# 本地图标库
|
||||
|
||||
> 这里缓存通过 `scripts/fetch_icon.py` 从 Iconify 拉下来的图标,**已入库一组商务红 tabler 种子集**(target / brain / chart-bar / users / trophy / alert-triangle / cpu / building-factory / cloud-network / database 等),覆盖大部分商务汇报场景。新场景模型按需 `fetch_icon.py` 拉,再次用时直接读本地不发请求。
|
||||
> 这里是 skill 自带的**只读种子图标库**,**已入库一组商务红 tabler 种子集**(target / brain / chart-bar / users / trophy / alert-triangle / cpu / building-factory / cloud-network / database 等),覆盖大部分商务汇报场景 —— 直接 `glob` 读用即可。docker 沙盒里 `skills/` 是只读挂载,**不能往这儿写**。新场景按需 `fetch_icon.py` 拉,落点是 `<task_dir>/assets/icons/`(可写),本 task 内再用直接读不发请求。
|
||||
|
||||
## 缓存命名规约
|
||||
|
||||
|
|
@ -13,10 +13,10 @@
|
|||
|
||||
## 推荐图标清单 (按业务主题)
|
||||
|
||||
按下面 3 行命令拉取首批最常用 18 个,够覆盖 80% 商务汇报场景:
|
||||
种子集已含下列大部分;若某个本 task 缺,按下面命令拉到 `<task_dir>/assets/icons/`(种子库只读,新图标进 task 目录):
|
||||
|
||||
```bash
|
||||
ICONS_DIR=<skill_dir>/assets/icons # <skill_dir> 来自 load_skill 头
|
||||
ICONS_DIR=<task_dir>/assets/icons # 可写落点;<skill_dir>/scripts 来自 load_skill 头(只读可执行)
|
||||
|
||||
# 战略 / 目标 / 启动
|
||||
for n in target rocket flag bulb; do
|
||||
|
|
|
|||
|
|
@ -13,21 +13,24 @@
|
|||
|
||||
## §A. Iconify 个性化图标 (本地缓存 + 网络拉取)
|
||||
|
||||
### A1. 本地库
|
||||
路径: `<skill_dir>/assets/icons/`,详见 [INDEX.md](../assets/icons/INDEX.md)。
|
||||
### A1. 本地库 (两处:只读种子库 + 本 task 已拉)
|
||||
- **种子库(只读)**: `<skill_dir>/assets/icons/` —— skill 自带的商务红 tabler 种子集,详见 [INDEX.md](../assets/icons/INDEX.md)。docker 沙盒里 `skills/` 是只读挂载,**只能读、不能往这儿写**。
|
||||
- **本 task 已拉**: `<task_dir>/assets/icons/` —— A2 fetch 新图标的落点(可写)。
|
||||
|
||||
命名规约: `<set>_<name>_<colorhex>_<sizepx>.png`(如 `tabler_rocket_C00000_128.png`)
|
||||
|
||||
**用之前先 `glob` 检查本地有没有**,有就直接 `add_picture`,免去网络往返。
|
||||
**用之前先 `glob` 两处都查一遍**(种子库 `<skill_dir>/assets/icons/` + 本 task `<task_dir>/assets/icons/`),有就直接 `add_picture`,免去网络往返。
|
||||
|
||||
### A2. fetch_icon.py 拉新图标
|
||||
脚本在 `<skill_dir>/scripts/`(只读可执行);拉下来的图标 `-o` **必须落 `<task_dir>/assets/icons/`**(种子库只读,新图标进 task 目录):
|
||||
```bash
|
||||
# 主红色 128px PNG (推荐)
|
||||
python <skill_dir>/scripts/fetch_icon.py rocket --set tabler --color C00000 \
|
||||
--size 128 -o <skill_dir>/assets/icons/tabler_rocket_C00000_128.png
|
||||
--size 128 -o <task_dir>/assets/icons/tabler_rocket_C00000_128.png
|
||||
|
||||
# 强调色金黄
|
||||
python <skill_dir>/scripts/fetch_icon.py target --set tabler --color FFC107 \
|
||||
--size 128 -o <skill_dir>/assets/icons/tabler_target_FFC107_128.png
|
||||
--size 128 -o <task_dir>/assets/icons/tabler_target_FFC107_128.png
|
||||
```
|
||||
|
||||
`--set` 默认 `tabler`(4500+ 商务图标,MIT)。其它选 `lucide / heroicons / material-symbols / carbon / fluent / mdi`。**整 deck 只用一个 set**。
|
||||
|
|
@ -37,7 +40,7 @@ PNG 转换需 `pip install cairosvg`(推荐)或 `pip install svglib`。没装也
|
|||
### A3. 嵌入幻灯片
|
||||
```python
|
||||
slide.shapes.add_picture(
|
||||
"<skill_dir>/assets/icons/tabler_rocket_C00000_128.png",
|
||||
"<task_dir>/assets/icons/tabler_rocket_C00000_128.png", # 路径 = glob 命中的那处(种子库或 task)
|
||||
Inches(1.0), Inches(2.5),
|
||||
width=Inches(0.8), # 装饰图标 0.5-1.5 in;别超 2 in
|
||||
)
|
||||
|
|
@ -53,7 +56,7 @@ slide.shapes.add_picture(
|
|||
```python
|
||||
from pptx.util import Inches, Pt
|
||||
stages = ["调研","设计","开发","测试","上线"]
|
||||
icon_path = "<skill_dir>/assets/icons/tabler_chevron-right_C00000_64.png"
|
||||
icon_path = "<task_dir>/assets/icons/tabler_chevron-right_C00000_64.png" # 先 fetch_icon.py 拉到 task,种子库没有 chevron-right_64
|
||||
for i, label in enumerate(stages):
|
||||
x = 0.7 + i * 2.4
|
||||
add_textbox(slide, x, 3.7, 1.8, 0.5, label, 16, bold=True,
|
||||
|
|
@ -90,7 +93,7 @@ python <skill_dir>/scripts/render_icon.py "✓" --color "#C00000" --size 96 -o <
|
|||
4. **不替表意** —— 一个 ★ 不能代替"重点"两字
|
||||
5. **避免 emoji** —— 跨系统渲染差异大,且自带颜色冲突主题
|
||||
6. **不要每页都堆** —— 装饰是配角,文字是主角
|
||||
7. **缓存复用** —— Iconify 拉的图标进 `assets/icons/` 缓存,下次直接用,不要重复请求
|
||||
7. **缓存复用** —— Iconify 拉的图标进 `<task_dir>/assets/icons/`,本 task 内再用直接读,不要重复请求(种子库 `<skill_dir>/assets/icons/` 只读,新图标不往那写)
|
||||
|
||||
## §D. 不要把 layouts.md helper 当"图标"
|
||||
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ caption 必须写、必须全 task 唯一 —— render_diagrams / quality_check
|
|||
|
||||
## 工作目录
|
||||
|
||||
`<task_dir>` = system prompt 给的**绝对路径**(`…/workspace/tasks/<task_id>/`)。**所有产物都写到 task_dir 下**,不要写到 cwd / `skills/` / repo 根。
|
||||
`<task_dir>` = system prompt 给的**绝对路径**(host 下形如 `…/workspace/users/<uid>/<wd>/`,docker 沙盒里是 `/workspace/<wd>/`)。**所有产物都写到 task_dir 下**,不要写到 cwd / `skills/` / repo 根。
|
||||
|
||||
```
|
||||
<task_dir>/
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ print(paper["abstract"])
|
|||
`has_fulltext_pdf=False` 或 `pdf_url` 空(publication_date 缺失)→ 抛 `RuntimeError`。
|
||||
|
||||
```python
|
||||
rel = fetch_pdf("10.1016/j.cemconres.2020.106156", working_dir=r"D:/projects/zcbot/workspace/users/<uid>/<wd>")
|
||||
rel = fetch_pdf("10.1016/j.cemconres.2020.106156", working_dir="<task_dir>") # <task_dir> = system prompt 给的工作目录绝对路径(docker 沙盒里形如 /workspace/<wd>)
|
||||
# rel == "papers/10.1016_j.cemconres.2020.106156.pdf"
|
||||
```
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue