面向微博灾害文本的地质灾害定位智能体。系统从微博正文、发布时间、发布位置、话题和匹配关键词等信息中识别已发生的地质灾害事件,抽取灾害类型、发生时间和地点,并将地点链接到标准行政区划、坐标和可选 GIS 风险信息。
当前公开评估以广东省行政区划为示例区域;如果替换行政区划表、知识图谱和 GIS 数据,同一套流程可以迁移到其他省份或区域。
这个项目面向地质灾害线索发现与空间归档场景,主要服务于需要整理灾害文本数据的研究人员、地理信息分析人员和应急信息研判人员。系统从微博、地方资讯等公开文本中识别已发生的灾害事件,并整理成可用于统计、地图展示和后续核验的标准化时空记录。
微博、短视频评论和地方资讯中经常会出现“白云山后山塌方”“省道 S248 线滑坡”“某服务区附近落石”这类口语化灾害描述。这些文本有三个典型问题:
- 信息表达不完整:很多文本只写简称、道路、服务区、村后山或景区,不直接给出标准行政区划;
- 地名存在歧义:同名村、同名街道和同名社区较多,单靠大模型容易把地点猜错;
- 研究和应急分析需要结构化结果:需要把微博文本转成“灾种、发生时间、标准行政区划、坐标、证据链”的数据表,才能用于统计、地图展示和后续风险分析。
因此,本项目的目标是把非结构化微博灾害文本转换为可追踪、可复核、可评估的地理定位结果,并在证据不足时主动降级或标记人工介入。
GeoparsingAgent/
├─ run.py # 直接运行/调试入口
├─ requirements.txt # Python 依赖
├─ .env.example # 环境变量模板,不包含真实密钥
├─ configs/
│ └─ settings.yaml # 非密钥类默认配置
├─ src/geoparsing_agent/
│ ├─ cli.py # 命令行入口
│ ├─ pipeline.py # LangGraph 总流水线
│ ├─ extractor.py # LLM JSON 信息抽取
│ ├─ admin_kg.py # 行政区划 KG 精确召回
│ ├─ matcher.py # 置信度路由与 Fast Path
│ ├─ agent.py # 不确定性处理 ReAct Agent
│ ├─ tools.py # 高德、微博位置、坡度等证据工具
│ ├─ gis.py # 坐标补全、坡度和地图输出
│ ├─ weibo_crawler.py # 轻量微博搜索爬虫
│ └─ schemas.py # 全流程统一数据结构
├─ process_data/
│ ├─ preprocess_weibo.py # 微博 CSV 清洗脚本
│ └─ build_guangdong_admin_kg.py # 行政区划 CSV/KG 构建脚本
├─ evaluation/
│ ├─ eval_set.csv # 公开评估集
│ ├─ predictions/ # DeepSeek/Gemini/消融实验预测结果
│ ├─ reports/ # 评估指标和误差分析
│ ├─ build_eval_set.py # 评估集抽样脚本
│ └─ evaluate.py # 评估脚本
├─ ori_data/ # 本地原始数据目录,不随仓库发布
├─ outputs/ # 本地运行输出目录,不随仓库发布
└─ tests/ # 测试目录
系统支持两种入口:
-
已有 CSV 数据
适合对已经清洗好的微博数据进行批量解析。CSV 至少需要包含微博正文,建议包含发布时间、发布位置、话题、匹配关键词等字段。
python run.py --mode process_csv --input-csv evaluation/eval_set.csv --output outputs/results.csv --limit 10
-
微博搜索爬虫
适合从关键词开始构造完整流程:LLM 生成搜索词,爬虫获取微博,随后进入 GeoHazard Geoparsing Agent。
python run.py --mode crawl_and_parse --stream-parse --crawl-keyword "广东 山体滑坡" --crawl-start-date 2024-01-01 --crawl-end-date 2024-01-07 --crawl-max-items 50
每条微博会输出结构化定位结果,主要字段包括:
- 是否为地质灾害语义;
- 事件状态:已发生、风险防御、历史背景、非灾害描述等;
- 灾害类型:滑坡、崩塌、泥石流、落石、地面沉降、其他地质灾害等;
- 灾害发生时间:原文时间、归一化日期和时刻;
- 行政定位结果:行政区划名称、层级、代码、完整路径;
- 坐标结果:经纬度、坐标证据来源;
- GIS 风险信息:坡度、风险等级,若本地提供坡度栅格;
- 证据与状态:Fast Path、Agent 决策、降级原因或人工介入原因。
输出文件包括:
outputs/results.csv 结构化结果
outputs/results.geojson 地理点位结果
outputs/map.html Folium 可视化地图
outputs/logs/ 运行日志和过程记录
微博文本 / CSV / 爬虫结果
-> 信息抽取节点
-> 行政区划 KG 召回节点
-> 置信度路由节点
-> Fast Path 或不确定性处理 Agent
-> GIS 补全节点
-> 结果保存与评估
使用 LLM JSON 模式抽取微博中的灾害事件信息:
- 是否为地质灾害语义;
- 是否为已经发生的灾害;
- 灾害类型,支持多灾种;
- 灾害发生时间;
- 与灾害发生相关的地点关键词。
这一步只做信息感知,不直接决定行政区划代码。
基于 NetworkX 构建行政区划知识图谱,当前示例使用广东省行政区划数据。系统会对 LLM 抽取出的地点关键词做严格召回,并返回候选行政路径。例如微博中抽取到 广州、白云、增城 时,KG 召回可能得到:
广州 -> 广东省/广州市
白云 -> 广东省/广州市/白云区
白云 -> 广东省/广州市/越秀区/白云街道
增城 -> 广东省/广州市/增城区
召回策略保持严格,只做精确匹配,不做拼音近似、编辑距离或模糊匹配。命中后提取候选节点的行政路径、祖先节点和上下文,作为后续路由和 Agent 决策依据。KG 召回本身不强行做语义判断,例如 广州白云、增城多地发生滑坡 会把相关候选交给后续 Agent 继续判断和组合。
系统会根据 KG 召回结果进行路由:
- 唯一、无歧义命中:进入 Fast Path,直接绑定标准行政区划;
- 多个同名候选、缺少上级信息、道路/POI/景区等非标准地点:进入不确定性处理 Agent;
- 非地质灾害、未发生事件或缺少地点:输出跳过或人工介入结果。
不确定性处理模块由 LangGraph 驱动。它接收微博正文、LLM 抽取结果、KG 候选路径和工具观测,逐步完成消歧。
ReAct Agent 能做的事情包括:
- 根据语义合并多个地点关键词和 KG 候选路径,例如把
广州、白云合并到广州市/白云区,也可以识别同一条微博中的多个灾害地点; - 对道路、服务区、景区、学校、村后山等非标准地点调用高德 POI 搜索,获取真实世界地点、坐标和所属行政区;
- 对组合行政路径或地址进行高德地理编码,例如
广东省韶关市乐昌市省道S248线; - 利用微博发布位置或签到地点作为更强的空间证据;
- 在已有坐标时查询坡度先验,辅助判断地质灾害空间合理性;
- 当高德证据明显指向初始 KG 候选之外的行政区时,允许扩展候选并重新决策;
- 提交
resolved、degraded或manual_required三类结构化结果,结束本轮推理。
Agent 的最终输出只允许三类:
resolved 证据闭环,定位到可信行政单元或坐标
degraded 证据不足以细化,降级到区县/乡镇等上级单元
manual_required 证据不足或超出当前行政区划范围,需要人工介入
GIS 节点负责把定位结果进一步转为空间输出:
- 对缺少坐标的行政结果调用地理编码补坐标;
- 根据本地坡度 GeoTIFF 查询缓冲区内的坡度和风险等级;
- 输出 GeoJSON;
- 生成 Folium 地图。
坡度栅格是可选数据。没有 slope.tif 时,主流程仍可输出行政定位和坐标,只是坡度与风险等级为空。
完整运行需要:
- LLM API:DeepSeek 或 Midea Gemini;
- 高德 Web Service API:POI 搜索、地理编码、逆地理编码;
- 行政区划数据:用于构建本地 NetworkX KG;
- 微博 Cookie:仅在使用爬虫模式时需要;
- 坡度栅格:可选,用于 GIS 风险补全。
.env.example 提供了配置模板。请复制为 .env 并填写自己的密钥:
copy .env.example .env核心配置示例:
EXTRACT_LLM_PROVIDER=deepseek
AGENT_LLM_PROVIDER=deepseek
DEEPSEEK_API_KEY=
AMAP_API_KEY=
MAX_WORKERS=3
LLM_MAX_CONCURRENCY=2
AMAP_MAX_CONCURRENCY=3公开评估集包含 100 条分层微博样本,覆盖已发生灾害、风险预警、非地质灾害语义、道路/POI/景区等复杂地点表达。Gold 字段经过人工复核。详细说明见 evaluation/README.md。
| 设置 | 已发生二分类准确率 | 灾种准确率 | 行政定位命中率 | 坐标覆盖率 | 已输出坐标 10km 命中率 |
|---|---|---|---|---|---|
| DeepSeek | 0.9700 | 0.9000 | 0.8261 | 0.9412 | 0.9375 |
| Gemini | 0.9500 | 0.9200 | 0.9130 | 1.0000 | 0.8235 |
| No-KG Ablation | 0.9600 | 0.9400 | 0.6087 | 1.0000 | 0.8824 |
No-KG 消融实验使用Gemini模型,会跳过行政区划 KG 召回和 Fast Path,直接让 Agent 结合文本与地图工具定位。对比结果显示,KG 上下文对标准行政单元绑定有明显贡献。
复现评估指标:
python evaluation/evaluate.py --gold evaluation/eval_set.csv --pred evaluation/predictions/deepseek.csv --out evaluation/reports/deepseek
python evaluation/evaluate.py --gold evaluation/eval_set.csv --pred evaluation/predictions/gemini.csv --out evaluation/reports/gemini
python evaluation/evaluate.py --gold evaluation/eval_set.csv --pred evaluation/predictions/no_kg_ablation.csv --out evaluation/reports/no_kg_ablation安装依赖:
conda create -n geoparsing python=3.12 -y
conda activate geoparsing
pip install -r requirements.txt运行单条样例:
python run.py --mode process_csv --input-csv evaluation/eval_set.csv --output outputs/debug_results.csv --limit 1 --offset 0 --debug运行完整评估集:
python run.py --mode process_csv --input-csv evaluation/eval_set.csv --output evaluation/predictions/deepseek.csv --limit -1 --checkpoint-every 10 --resume运行 No-KG 消融:
python run.py --mode process_csv --input-csv evaluation/eval_set.csv --output evaluation/predictions/no_kg_ablation.csv --limit -1 --ablation no_kg长任务支持 checkpoint 和续跑:
python run.py --mode process_csv --limit -1 --checkpoint-every 10 --resume| 参数 | 说明 |
|---|---|
--mode |
运行模式。process_csv 读取已有 CSV;crawl_only 只爬取微博;crawl_and_parse 爬取后进入定位流程。 |
--input-csv |
process_csv 模式的输入 CSV。不传时读取 .env 中配置的默认清洗数据。 |
--output |
结果 CSV 输出路径。不传时默认写入 outputs/results.csv;调试模式默认写入 outputs/debug_results.csv。 |
--limit |
本次最多处理多少条微博。-1 表示从 offset 后处理全部记录,不表示并行数。 |
--offset |
从输入 CSV 的第几条开始处理,适合分段测试或复查问题样本。 |
--weibo-id |
只处理指定微博 id,适合单条复查。 |
--resume |
从已有输出 CSV 续跑,跳过已经完成的微博记录。 |
--checkpoint-every |
每处理多少条追加保存一次结果 CSV,长任务建议设置为 10 或 20。 |
--ablation |
消融实验开关。none 为正常流程;no_kg 跳过 KG 召回和 Fast Path。 |
--debug |
调试模式,默认输出到 outputs/debug_results.csv,适合 VS Code 单条调试。 |
--verbose |
输出更详细的运行日志。 |
--crawl-keyword |
手动指定微博搜索词,可重复传入;不传时可由 LLM 生成搜索词。 |
--crawl-keyword-file |
从文本文件读取搜索词,每行一个。 |
--crawl-start-date / --crawl-end-date |
爬虫日期范围,格式为 YYYY-MM-DD。 |
--crawl-region |
爬虫地区约束,例如 广东。 |
--crawl-max-items |
本次爬虫最多保留多少条微博。 |
--crawl-query-count |
由 LLM 生成多少个搜索词。 |
--crawl-query-strategy |
搜索词生成策略,例如 balanced 或 high_recall。 |
--stream-parse |
crawl_and_parse 模式下边爬边解析。 |
--stream-batch-size |
流式解析的批大小。 |
并行数由 .env 中的 MAX_WORKERS、LLM_MAX_CONCURRENCY 和 AMAP_MAX_CONCURRENCY 控制。高德 API 默认建议最高并发不超过 3。
为了避免泄露隐私、凭证和大体积数据,公开仓库不包含:
.env;- 原始微博全量数据;
- 清洗后的全量微博数据;
ori_data/slope.tif等大体积 GIS 栅格;- 运行日志、调试 CSV、Folium 地图等本地输出。
公开仓库保留代码、评估集、预测结果和评估报告。全量微博数据可以基于本地 CSV 使用同一条 pipeline 运行。
这个项目的实现重点包括:
- 使用 LangGraph 编排多节点工作流,而不是单轮 prompt;
- 将 LLM 抽取、知识图谱召回、规则路由和工具调用组合成可控 Agent;
- 用
finish_resolution约束 Agent 最终输出,降低自由发挥; - 为工具调用设置预算、缓存和结构化 observation;
- 支持 Fast Path、Agent Path、Graceful Degradation 和 Manual Required;
- 通过消融实验验证 KG 对定位效果的贡献;
- 通过 checkpoint/resume 和并发控制支持较长批处理任务;
- 将 Agent 输出接入 GIS 结果、GeoJSON 和地图可视化。
- 当前公开评估以广东省为示例区域,迁移到其他区域需要替换行政区划 KG 和可选 GIS 数据。
- 微博文本经常缺少精确地点,系统会根据证据降级,而不是强行输出村级结果。
- 道路、服务区、景区、多地泛称等表达仍是主要难点。
- 大规模运行会消耗 LLM 和高德 API 配额,建议使用 checkpoint/resume。