Tobacco Agent —— 面向烤烟(flue-cured tobacco)生产特点的农事规划智能体, 是论文《叶位成熟积温驱动的烤烟采收—烘烤协同农事规划智能体》的完整实现与实验代码。
本仓库同时保留了其前身 AgriPlan-Agent 的通用多模态应用层(Streamlit 交互界面、 田间图像分析、气象查询),以便读者对照"通用农业智能体"与"烤烟专用智能体"的差别。
一句话说明本系统在做什么: 把逐日气象数据,经由叶位成熟积温模型转换为叶位成熟状态, 再在烤房产能与农艺硬约束下求解采收—烘烤协同调度, 最终输出一份可直接下田执行的逐日农事方案。
四个环节顺次衔接,构成论文图 1 的主线。带 [重点] 的两层是本研究相对通用农业 智能体新增的部分。
① 气象数据 逐日最高/最低气温、降水、湿度
│ (eval/scenarios.py 生成受控合成情景;
│ modules/tool_dispatcher.py 接入实测预报)
▼
② 叶位成熟状态 [重点] 有效积温(GDD)驱动的物候推进与叶位成熟期预测
│ tobacco/phenology.py + tobacco/climate_risk.py
▼
③ 产能与农艺约束 [重点] 烤房容量约束下的采收—烘烤批调度
│ tobacco/curing_scheduler.py
│ 10 条可引证的农艺硬约束(TACL)
│ tobacco/agronomy_rules.py
▼
④ 可执行农事方案 语言模型据上述结论生成逐日方案,
再经确定性校验器判定违规并回灌修正
tobacco/verifier.py + modules/llm_responses.py
关键设计:校验环节不依赖语言模型。约束判定由 tobacco/verifier.py 用确定性
规则完成,因此"违规率"是可复现的客观指标,而非模型自评(避免自评偏倚,
self-evaluation bias)。
| 路径 | 说明 |
|---|---|
tobacco/ |
烤烟专用领域组件(Tobacco-Specific Domain Components),本研究的核心贡献 |
tobacco/ontology.py |
烤烟农事本体(受控词表),术语依 YC/T 142-2010,把自由文本映射为可判定谓词 |
tobacco/phenology.py |
物候—叶位有效积温模型;叶位成熟积温呈非线性加速,锚定钱益亮等(2013)三个可引证点 |
tobacco/agronomy_rules.py |
农艺硬约束库(TACL),10 条约束逐条标注文献或标准出处,分 critical/major/minor 三级 |
tobacco/climate_risk.py |
关键期气象风险判据;总纲为 QX/T 363-2016,未获原件条文处采用可核实的替代判据并显式标注 |
tobacco/curing_scheduler.py |
烤房容量约束下的采收—烘烤协同调度(带资源约束的批调度) |
tobacco/verifier.py |
约束校验器与反思重规划:解析方案 → 判定违规 → 生成修正指令 |
eval/ |
消融实验:情景生成、四/五级条件运行器、指标汇总,以及论文所用的原始记录 |
eval/scenarios.py |
受控合成气象情景生成器(4 气象情景 × 2 移栽期 × 2 烤房配置 = 16 情景) |
eval/run_ablation.py |
消融实验主运行器,支持断点续跑与并发 |
eval/analyze.py |
把 results.jsonl 汇总为论文表 A~D |
eval/*.jsonl |
论文所用的原始实验记录(生成文本 + 逐条指标),可据此完全复算全部数值 |
modules/llm_responses.py |
Responses 接口客户端(只用标准库 urllib),供 eval/ 调用 |
modules/llm_planner.py |
Chat Completions 接口客户端与提示词拼装,供交互界面调用 |
modules/tool_dispatcher.py |
气象服务调用(逐日预报、气象预警) |
modules/vision_analyzer.py |
田间图像分析(视觉语言模型,VLM),可选功能 |
modules/ui_input.py |
Streamlit 表单与地图选点 |
core/config.py |
统一凭据加载器:环境变量优先,源码内不含任何密钥与服务地址 |
core/context.py |
智能体上下文数据模型(pydantic) |
knowledge_engine/ |
向量检索知识库(FAISS + sentence-transformers),预留模块 |
main.py |
Streamlit 交互界面入口 |
config/settings.example.yaml |
配置模板,不含任何真实值 |
SECURITY.md |
安全与隐私说明:凭据放在哪里、发布前自检脚本 |
CHANGELOG.md |
变更日志 |
依赖分三层,按实际用途安装即可。
第一层:只跑领域模块与消融实验(推荐先从这一层开始)
tobacco/ 与 eval/ 的情景生成、指标计算全部只用 Python 标准库,
无需安装任何第三方包:
python -c "import sys; sys.path.insert(0,'.'); from tobacco.phenology import leaf_maturity_gdd; print(leaf_maturity_gdd(10))"第二层:调用真实语言模型跑消融实验
pip install PyYAML requests第三层:完整交互界面
pip install -r requirements.txt
streamlit run main.py要求 Python 3.9 及以上。
本仓库不含任何 API 密钥或服务地址。 所有凭据一律来自运行环境,
由 core/config.py 在真正发起请求的时刻才读取——未配置时模块照常导入,
不联网的领域模块与实验情景生成完全不受影响。
方式一:环境变量(推荐,不落盘、不会被误提交)
export LLM_API_KEY="<你的密钥>"
export LLM_API_HOST="<你的服务地址>" # 需支持 /responses 端点
export LLM_MODEL="<你的模型名>"方式二:本地配置文件(已被 .gitignore 排除)
cp config/settings.example.yaml config/settings.yaml
# 编辑 config/settings.yaml,把 <尖括号占位符> 换成自己的值全部可配置项:
| 用途 | 环境变量 | 配置文件字段 | 必需性 |
|---|---|---|---|
| 语言模型 | LLM_API_KEY / LLM_API_HOST / LLM_MODEL / LLM_MODEL_REASON |
llm.* |
生成农事方案时必需 |
| 视觉模型 | VLM_API_KEY / VLM_API_HOST / VLM_MODEL |
vlm.* |
仅图像分析功能需要 |
| 气象服务 | QWEATHER_API_KEY / QWEATHER_API_HOST |
qweather.* |
仅接入实测预报时需要 |
环境变量优先级高于配置文件;模板中形如 <YOUR_API_KEY> 的占位符会被识别为"未配置"。
本项目不绑定任何特定服务商,填入任何与 OpenAI 接口兼容(OpenAI-compatible)的地址即可。
详细步骤见 eval/README.md。要点:
# 在项目根目录执行;16 情景 × 4 条件 = 64 条任务,4 路并发约 1~2 小时
python eval/run_ablation.py --effort xhigh --workers 4
# 汇总为论文表 A~D
python eval/analyze.py
python eval/analyze.py --csv eval/tables中断后重新执行同一条命令即可,脚本会读取 results.jsonl 自动跳过已完成任务。
五个消融条件(累进):
| 条件 | 注入内容 |
|---|---|
| A 基线 | 仅地块基本信息(产区、品种、面积、移栽日期、留叶数、烤房数) |
| B +气象上下文 | A +未来 30 天逐日气象预报(即通用农业智能体的做法) |
| P +叶位成熟状态 | B +物候—叶位积温分析、关键物候时点、气象风险研判(不含装炕安排) |
| C +协同调度 | P +烤房产能约束下的采收—烘烤调度建议 |
| D +校验重规划 | C +农艺约束校验,把违规清单与文献依据回灌给模型做一轮修正 |
拆出 P 是为了区分改善究竟来自"叶位成熟状态"还是"协同调度"。
条件 D 另有严格配对版 eval/run_paired_d.py,直接在条件 C 的同一份初稿上执行
校验重规划,排除重新采样带来的波动。
若不想调用模型,eval/reeval.py 可在已保存的生成文本上重算指标(校验器标定变更时使用)。
eval/scenarios.py 生成的是受控合成情景,论文中已明确声明,
不冒充任何具体年份的实测气象记录。
基准温度过程由一个可公开核实的锚点反演:襄城县(河南许昌核心烟区)多年平均
年均温 14.9 ℃、≥10 ℃ 活动积温 4770.5 ℃·d(襄城县人民政府基层政务公开
《基本水文资料》,2023-09-08)。以此二者为约束,用二分法反解正弦型年温度过程的
振幅,得 A ≈ 12.695 ℃。胁迫情景在基准过程上叠加显式定义的扰动
(幅度、起止、持续天数均写明在 SCENARIOS 中),随机种子固定,结果可复现。
要换用真实气象数据,只需让 generate_weather() 返回同样结构的
List[DailyWeather](字段 day / tmin_c / tmax_c / precip_mm / humidity_pct),
下游模块无需改动。
main.py 是前身 AgriPlan-Agent 的 Streamlit 界面,分三步走:
基础信息与地块选点 → 目标设定与逐日计划 → 实时问答与图像诊断。
截图中的地块名称、面积、土壤指标与经纬度均为演示用示例值,不对应任何真实生产地块。
- 仓库内不含任何 API 密钥、服务地址、账号或个人信息;
config/settings.yaml、.env、*.key等已在.gitignore中排除。 eval/下的*.jsonl是论文所用的原始实验记录,按学术诚信原则原样保留, 未作任何数值修改。其中的模型标识、token 计数、耗时等字段用于说明实验条件。- 田间照片可能携带地理位置等 EXIF 信息,
.gitignore已排除*.jpg/*.jpeg/*.webp; 上传的图像只写入系统临时目录,不进入仓库。 - 若要把本仓库推到公开托管平台,请新建一个空仓库并提交当前工作副本, 不要沿用任何旧仓库的提交历史——历史记录中可能残留曾经写死的密钥。
若本代码对你的研究有帮助,请引用对应论文(见 CITATION.cff)。
论文正式发表后请以期刊版信息为准。
本项目遵循 MIT 开源协议,可自由使用、修改与集成,用于科研或实际部署。
MIT License © 2025








