版本 2.1.3(实际版本以 QGIS 插件管理器显示为准)| 将大语言模型嵌入QGIS的智能助手
用自然语言操控 QGIS,无需编写代码
本文档是产品路线图 + 使用手册,其中部分能力仍处于规划阶段、尚未接入对话链路。带 规划中 · 当前不可用 标记的功能在当前版本中无法使用,包括:
skills/)—— 代码中存在实现,但生产链路零引用workflow_recorder.py、workflow_executor.py)—— 未接线clarification_manager.py)—— 未接线task_graph.py)—— 未接线其余未标注的能力均为当前版本实际可用功能。宁可少宣传,也不希望您装了发现用不了。
🖥️ QGIS 主线程(GUI)
┌──────────────────────────────────────────────────────────────┐
│ 🧩 QGISAgent(主控制器) ──▶ 🪟 DockWidget(UI 面板) │
│ └─▶ 💬 Conversation(会话管理) │
└───────────────────────────────┬──────────────────────────────┘
│ async_response
▼
⚙️ 工作线程(QThreadPool)
┌──────────────────────────────────────────────────────────────┐
│ 🔧 ToolAgentWorker(异步执行)──▶ 🧠 Processor(Agent 循环) │
└───────┬───────────────┬──────────────────────┬───────────────┘
│ │ │
│ 检索文档 │ 检索工具 │ API 调用
▼ ▼ ▼
📚 RAG 引擎(本地) ☁️ 外部服务
┌──────────────────────────────┐ ┌────────────────────────┐
│ 📖 DocStore(SQLite FTS5) │ │ 🤖 LLM API │
│ 🔍 Retriever(关键词搜索) │ │ DeepSeek / OpenAI │
│ 🧰 ToolDocs(679 个算法文档) │ │ 兼容端点 │
└──────────────────────────────┘ └────────────────────────┘
│ 跨线程调用工具
▼
🔩 QGIS 工具层(主线程调度)
┌──────────────────────────────────────────────────────────────┐
│ 📞 call_tool()(线程桥)──QTimer──▶ 🧰 19 个 QGIS 工具 │
│ └▶ 🗺️ QGIS API │
│ QgsProject / iface / │
│ Processing │
└──────────────────────────────────────────────────────────────┘
qgis_agent_v2.1.3_20260902.zip
https://api.deepseek.com/v1| 提供商 | API 端点 | 模型 |
|---|---|---|
| DeepSeek | https://api.deepseek.com/v1 | deepseek-chat |
| OpenAI | https://api.openai.com/v1 | gpt-4o, gpt-4o-mini |
| 智谱 GLM | https://open.bigmodel.cn/api/paas/v4/ | glm-4, glm-4-flash |
https://generativelanguage.googleapis.com/v1beta/openai/ | gemini-2.0-flash | |
| 小米 MiMo | https://api.xiaomimimo.com/v1 | mimo-v2.5 |
| 自定义 | 任何 OpenAI 兼容接口 | 任意模型名 |
http://localhost:11434/v1 或你的内网地址)。403 PermissionDenied,插件已自动附加浏览器 User-Agent 绕过 Bot 防护;如仍被拦,请检查 Cloudflare 的 Bot Fight Mode 设置。| 操作 | 示例指令 | 预期结果 |
|---|---|---|
| 查询 | 查看当前项目有哪些图层 | 显示图层列表和属性 |
| 加载 | 添加图层 D:/data/roads.shp | 加载矢量图层 |
| 分析 | 对道路图层做100米缓冲区分析 | 执行缓冲区分析 |
| 分析 | 用AOI图层裁剪道路图层 | 执行裁剪分析 |
| 分析 | 筛选面积大于100的建筑 | 属性查询筛选 |
| 输出 | 将地图渲染导出为PNG | 导出地图截图 |
执行代码前自动查询 PyQGIS API 签名和参数,确保代码准确性:
用户请求 ──▶ Query Tuning ──▶ RAG 检索 ──┬──▶ PyQGIS API 文档 ──┐
└──▶ Processing 工具文档 ┘
│
▼
LLM 生成代码
│
执行分析 ◀────────┘
│
▼
返回结果
用户: 对道路图层做缓冲区分析
↓
RAG 检索: QgsVectorLayer, processing.run
↓
LLM 生成: 准确的 PyQGIS 代码
↓
执行: 缓冲区分析完成
代码执行失败时,自动分析错误并提供修复建议:
| 错误类型 | 识别模式 | 修复建议 |
|---|---|---|
| ImportError | ModuleNotFoundError | 检查库安装,尝试替代导入 |
| QgsVectorLayer 错误 | invalid layer | 检查路径,验证图层有效性 |
| Processing 算法错误 | Algorithm not found | 检查算法ID,验证参数 |
| 几何错误 | Invalid geometry | 使用 buffer(0) 修复 |
| 字段错误 | Field not found | 检查字段名,验证数据类型 |
| 内存错误 | MemoryError | 分块处理,简化几何 |
当前版本无法使用。设计目标:将对话中的工具调用序列保存为可重用工作流
(workflow_recorder.py / workflow_executor.py 代码已存在,但尚未接入对话链路):
第一次对话 ─▶ 执行工具链 ─▶ 录制工作流 ─▶ 保存为模板
│
第二次对话 ◀─────────────────────────────────┘
│
▼
加载工作流 ─▶ 参数替换 ─▶ 直接执行 ─▶ 返回结果
# 录制工作流
workflow = recorder.record_from_conversation(
tool_calls=[
{"tool": "native:buffer", "args": {"INPUT": "${input_layer}", "DISTANCE": "${distance}"}},
{"tool": "native:savefeatures", "args": {"OUTPUT": "${output_path}"}}
],
workflow_name="缓冲区分析工作流"
)
# 下次直接执行
results = executor.execute_workflow(
template=workflow,
parameters={
"input_layer": "D:/data/rivers.shp",
"distance": 200,
"output_path": "D:/output/rivers_buffer.shp"
}
)
当前版本无法使用。设计目标:识别模糊或不完整的请求,主动向用户澄清
(clarification_manager.py 尚未接入对话链路):
| 用户输入 | 识别问题 | Agent 提问 |
|---|---|---|
分析一下 | 请求模糊 | 请具体说明要分析什么内容 |
添加图层 | 缺少路径 | 请提供数据文件的完整路径 |
缓冲区分析 | 缺少距离 | 请指定缓冲区距离(单位:米) |
按字段筛选 | 缺少字段 | 请指定要使用的字段名称 |
| 工具 | 功能 | 分类 | 示例 |
|---|---|---|---|
get_qgis_info | 获取项目信息 | 📊 查询 | 查看当前项目有哪些图层 |
get_layer_features | 查询图层属性 | 📊 查询 | 查看道路图层的属性表 |
add_vector_layer | 添加矢量图层 | 📂 管理 | 添加图层 D:/data/roads.shp |
add_raster_layer | 添加栅格图层 | 📂 管理 | 添加栅格 D:/data/dem.tif |
remove_layer | 移除图层 | 📂 管理 | 移除道路图层 |
zoom_to_layer | 缩放到图层 | 🔎 导航 | 缩放到道路图层 |
set_layer_labeling | 设置图层标注 | 🏷️ 标注 | 显示道路名称标注 |
execute_processing | 执行 Processing 算法 | ⚙️ 分析 | 执行缓冲区分析 |
execute_pyqgis | 执行 PyQGIS 代码 | 🐍 高级 | 自定义空间分析 |
search_pyqgis_api | 检索 API 文档 | 📚 RAG | 查询 QgsGeometry 方法 |
render_map | 渲染地图截图 | 📸 输出 | 导出当前地图为PNG |
save_project | 保存项目 | 💾 项目 | 保存当前项目 |
load_project | 加载项目 | 💾 项目 | 加载项目文件 |
save_memory | 保存长期记忆 | 🧠 记忆 | 记住用户偏好 |
load_memory | 加载长期记忆 | 🧠 记忆 | 读取之前保存的信息 |
get_algorithm_parameters | 查询 Processing 算法参数 | 📚 RAG | 查 native:buffer 需要哪些参数 |
get_layer_profile | 生成图层数据概览 | 📊 查询 | 看看这个图层有哪些字段 |
set_layer_renderer | 设置图层渲染样式 | 🎨 渲染 | 按高度字段分级设色 |
reproject_layer | 图层投影转换 | ⚙️ 分析 | 把这个图层转到 EPSG:3857 |
共 19 个内置工具,清单与代码中的
qgis_tools.TOOL_DEFINITIONS 保持一致。
内置 679 个 QGIS Processing 工具 文档,支持 RAG 检索:
用户请求 ──▶ 工具检索 ──┬──▶ native:buffer
├──▶ native:clip
├──▶ native:intersection
├──▶ native:dissolve
└──▶ … 共 679 个算法文档
│
▼
参数说明 ──▶ 代码示例 ──▶ LLM 生成代码 ──▶ 执行分析
| 前缀 | 说明 | 示例工具 |
|---|---|---|
native: | QGIS 原生算法 | buffer, clip, dissolve, intersection |
gdal: | GDAL/OGR 工具 | aspect, slope, contour, rasterize |
qgis: | QGIS 扩展工具 | heatmap, idw, tininterpolation |
3d: | 3D 分析工具 | tessellate |
pdal: | 点云处理工具 | boundary, density, filter |
添加图层 D:/data/roads.shp对道路图层做100米缓冲区分析用AOI图层裁剪道路图层添加图层 roads.shp(可能找不到文件)分析一下(不知道要分析什么)缓冲区分析(没有指定距离)加载数据、分析、保存(建议分步执行)| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 插件无法加载 | QGIS 版本不支持 | 请使用 QGIS 3.0+ 或 4.x(插件已 PyQt5/PyQt6 双兼容) |
| API 调用失败 | 网络连接或密钥错误 | 检查网络和 API 密钥 |
| 返回 403 PermissionDenied | Cloudflare / 网关拦截 Python 客户端 | 本地模型可留空 Key;插件已自动附加浏览器 UA,若仍被拦请检查 Cloudflare Bot Fight Mode |
| 代码执行错误 | 语法或参数错误 | 查看 SmartDebugger 的修复建议 |
| 图层加载失败 | 文件路径错误 | 检查文件路径是否正确 |
| 工具调用失败 | 算法ID或参数错误 | 使用 search_pyqgis_api 查询正确用法 |
| 内存不足 | 数据量过大 | 分块处理或简化几何 |
加载道路图层 ──▶ 执行缓冲区分析 ──▶ 保存结果 ──▶ 加载结果图层
# 缓冲区分析工作流代码
import processing
from qgis.core import QgsVectorLayer, QgsProject
# Step 1: 加载道路图层
roads = QgsVectorLayer('D:/data/roads.shp', 'roads', 'ogr')
QgsProject.instance().addMapLayer(roads)
# Step 2: 执行缓冲区分析
result = processing.run('native:buffer', {
'INPUT': 'D:/data/roads.shp',
'DISTANCE': 100,
'SEGMENTS': 25,
'END_CAP_STYLE': 0,
'JOIN_STYLE': 0,
'DISSOLVE': False,
'OUTPUT': 'D:/output/roads_buffer.shp'
})
# Step 3: 加载结果图层
buffer_layer = QgsVectorLayer(result['OUTPUT'], 'roads_buffer', 'ogr')
QgsProject.instance().addMapLayer(buffer_layer)
print('缓冲区分析完成!')
加载土地利用图层 ──▶ 加载行政区划图层 ──▶ 执行相交分析 ──▶ 统计各区域面积 ──▶ 导出结果
remove_layer / load_project / save_project,覆盖文件写入时确认