AI 智能体如何把「一句话」变成一张分析图
目录
1 引言:空间分析的能力供给与使用门槛
1.1 问题的工程化表述
1.2 解法:把「人话」翻译成「地图操作」
2 总体架构:从对话到成图的四层链路
3 核心技术拆解
3.1 意图理解与工具调用
3.2 字段语义层:翻译与防臆造校验
3.3 低代码场景引擎:能力注册与编排
3.4 空间计算内核
3.5 数据链路与持久化
3.6 状态与反馈模型
4 端到端链路:县域企业影响分析(平度市案例)
5 代码示例:HeatmapAgent 的「感知—决策—执行—汇报」模式
6 与常规 GIS 二次开发的对比
7 工程取舍与可观测的边界
8 结语
产业分析真正的难点,不在数据,而在「从数据到地图」之间的那道鸿沟。本文从技术视角拆解——一个以 AI 智能体与低代码场景引擎为核心的空间分析:它如何把一句句自然语言需求,解析为可执行的图层、样式、分析与组件操作,并实时呈现在地图上。全文以一次真实的县域产业分析为例,覆盖意图理解、字段校验、能力编排、空间计算、数据持久化等关键链路。
1 引言:空间分析的能力供给与使用门槛
1.1 问题的工程化表述
「做业务的人不懂 GIS,懂 GIS 的人不懂业务」,是政务、园区、招商团队中常年存在的分工困境。从工程视角看,一次空间分析交付至少包含五类环节:数据准备、坐标基准对齐、图层组织、空间分析与统计、结果表达,每一环都对应独立的专业工具与技能要求。
以「龙头企业影响圈覆盖了多少上下游企业」这类问题为例,完整链路包括坐标转换、图层叠加、缓冲区分析、覆盖统计与结果汇总。在常规工作流中,这些环节需要数据工程师、GIS 工程师与业务人员多轮协作:找数据、导出 Excel、提交开发、等待排期、反复沟通样式与口径,最终拿到的往往还是一张可能已经过时的图。
1.2 解法:把「人话」翻译成「地图操作」
不要求业务人员学习 GIS,也不依赖开发排期,而是把空间分析能力封装为可编排的能力原子,由 AI 智能体将自然语言需求翻译为能力调用序列,在低代码场景引擎中逐一执行并实时呈现。用户的核心动作只有一个——像聊天一样,把分析需求说出来。
2 总体架构:从对话到成图的四层链路
不是把 GIS 操作搬上对话框,而是一套「会干活」的智能体。整体架构可抽象为四层:
交互层:对话输入与地图画布双通道。用户以自然语言下达指令,所有操作结果实时呈现在地图上;发现偏差时,用一句话即可纠正。
意图理解层:将中文需求解析为结构化操作指令,包括意图识别、槽位抽取与参数映射,输出标准化的工具调用序列。
能力编排层:按需组合图层、样式、分析、组件等十余项开箱即用能力,复杂需求自动拆解为多步操作序列。
数据与执行层:低代码场景引擎执行操作,支撑图层入库、字段查询、空间计算与数据库访问;支持对话生成 SQL,直接查询业务数据。
四个层面共同保证一条设计原则:每一步操作都可解释、可纠正、可持久化——工具调用过程在对话面板中可见,操作结果即时上图,最终成果可保存为场景与图层资产。
3 核心技术拆解
3.1 意图理解与工具调用
将 GIS 操作封装为一组带参数的工具,智能体通过工具调用完成「一句话 → 操作序列」的翻译。以界面中可见的调用为例:
修改图层样式:update_layer_style,参数包括 fullColor、borderColor、borderWidth、opacity;
多条件过滤:filter_layer_data,参数为图层 ID 与 conditions 数组,多个条件以 AND 连接;
覆盖分析:analyze_buffer_coverage,可指定统计字段完成汇总。
对于「过滤出注册资本大于 500、2025 年以后成立的企业」这类需求,智能体将其拆解为两个条件(注册资本大于 500 且成立日期不早于 2025),以 AND 组合后调用 filter_layer_data。条件中的字段名与比较符由字段语义层提供,而非模型自由生成。
3.2 字段语义层:翻译与防臆造校验
自然语言中的业务字段(如「注册资本」「成立日期」)与数据表中的真实字段(如 REGCAP、idate)并非一一对应。若让模型直接生成字段名,极易出现「臆造字段」。智能体的应对方式是字段先翻译、再校验:
解析上传文件时识别字段清单,维护字段元数据;
工具调用前先经 list_layer_fields 预取目标图层的字段编码;
将需求中的业务字段映射为真实字段,并在调用前校验参数合法性,杜绝臆造字段名。
这一机制同时服务两类场景:过滤条件的构建,以及覆盖分析中统计字段(sumFields)的指定。
3.3 低代码场景引擎:能力注册与编排
低代码场景引擎沉淀了四类能力,见表1。
表1 智能体核心能力清单
|
能力类 |
包含能力 |
|
图层类 |
图层列表、创建图层入库、向已有图层追加数据、字段清单翻译 |
|
样式类 |
属性修改、图标与位图替代、数据标签、分级分类着色 |
|
地理分析类 |
缓冲区分析、面转点、坐标系转换、缓冲区覆盖分析 |
|
筛选与组件 |
多条件过滤、属性框组件、图层数据过滤 |
引擎按「能力注册表 + 组合编排」工作:每条指令被解析为一个或多个能力调用,能力之间可串联。例如覆盖分析并非单次调用:需要先获取字段编码(list_layer_fields),再执行 analyze_buffer_coverage 并指定统计字段,复杂分析因此可以被逐步执行、逐步确认。
3.4 空间计算内核
空间计算内核提供基础几何算子与分析算子两类能力:
坐标系转换:支持 GCJ02 与 WGS84 等坐标系互转。企业坐标从 GCJ02 转成 WGS84 后,点位与底图精准对齐,解决「漂移」问题;
缓冲区分析:以指定要素为中心、按半径生成缓冲区(如 10 千米影响圈),并支持保存为独立图层;
缓冲区覆盖分析:统计缓冲区覆盖范围内的要素数量与字段汇总(覆盖几个乡镇、多少企业、注册资本合计);
面转中心点:将面要素(如乡镇行政区划)转换为中心点图层,供后续分析使用;
分级分类着色:按字段值分档映射色阶(如按注册资本分 5 档:绿、黄、蓝、橙、紫),也支持按行政区编码分档着色;
热力渲染:将点要素渲染为热力分布,直观呈现区域密度差异。
3.5 数据链路与持久化
文件解析与入库:上传 CSV 或 Excel 后,智能体解析数据条数、识别要素类型(点或面)与字段清单;数据量较大时,地图预览仅渲染部分点位,入库时以后端解析的全量数据为准,保证统计口径完整。
图层资产:操作生成的临时图层(如影响圈、中心点)不会自动入库;经用户确认后,可保存为正式图层入库并返回图层 ID,成为可复用的图层资产。
场景存档:场景记录图层集合、初始视图(经纬度与层级)与配置,保存后整体复用,下次分析从「继承」开始。
对话式 SQL:智能体可直接生成 SQL 查询数据库,打通「数据—地图—分析—决策」整条链路。
3.6 状态与反馈模型
「前端暂存 + 显式持久化」的状态模型:样式、过滤等配置暂存于前端,点击「保存场景」后才持久化到后端。这一设计让操作具备即时的可逆性与可见性——每一步操作都在地图上即时呈现,发现偏差可以用一句话纠正,最终成果经确认后统一落库。
4 端到端链路:县域企业影响分析(平度市案例)
以平度市为例,将企业数据导入,完整演示一次企业影响分析。全过程由对话驱动,九步的指令、底层动作与呈现效果见表2。
表2 九步分析的技术链路映射
|
步骤 |
用户指令(节选) |
底层动作 |
地图呈现 |
|
1 数据一键上图 |
「把上传的文件生成新图层,图层名称:平度企业」 |
文件解析(4096 条点数据)、字段识别、创建图层入库 |
企业点位图层叠加行政底图 |
|
2 数据真实叠加 |
「企业坐标从 GCJ02 转成 WGS84」 |
坐标系转换算子 |
点位与底图精准对齐 |
|
3 企业热力分布 |
「生成热力图」 |
热力渲染 |
热力图层,密度分布一目了然 |
|
4 资本格局 |
「按注册资本分 5 档上色」 |
分级分类着色(5 档色阶) |
资本集聚格局一眼看清 |
|
5 重点企业画像 |
「注册资本大于 500、成立日期 ≥ 2025」 |
filter_layer_data 多条件过滤(AND 组合) |
新设重点企业被单独圈出 |
|
6 点选看详情 |
点击任意企业 |
属性框组件绑定要素查询 |
工商信息卡片随点随看 |
|
7 龙头企业影响圈 |
以龙头公司为中心生成影响圈 |
缓冲区分析(示例半径 10 千米) |
辐射圈瞬间生成 |
|
8 龙头带动能力量化 |
「统计影响圈覆盖几个乡镇、多少企业,汇总注册资本」 |
list_layer_fields + analyze_buffer_coverage |
覆盖统计结果量化呈现 |
|
9 成果固化复用 |
「保存影响圈为正式图层」「面转中心点」「保存场景」 |
临时图层转正式图层入库、面转点、场景序列化 |
图层资产与场景存档 |
步骤1 数据一键上图:上传企业数据后,智能体解析并识别为点数据,同时列出字段清单;一句「把上传的文件生成新图层,图层名称:平度企业」即完成图层创建与上图,再上传乡镇行政区划,行政底图就位。
图1 数据解析与图层管理
步骤2 数据真实叠加:上传数据的坐标若为 GCJ02,与 WGS84 底图存在偏移;一句「企业坐标从 GCJ02 转成 WGS84」完成坐标系转换,点位与底图精准对齐,不再漂移。
步骤3 企业热力分布:「生成热力图」将点位渲染为热力分布,企业密集区与稀疏区一眼看清;图中右侧可见 update_layer_style 工具调用的参数(fullColor、opacity 等)。
图2 热力分布与样式工具调用
步骤4 资本格局:「按注册资本分 5 档上色」,绿、黄、蓝、橙、紫五档色阶呈现资本规模集聚格局;乡镇层面再按行政编码分档着色,区域差异一目了然。
步骤5 重点企业画像:通过多条件过滤「注册资本大于 500」且「成立日期 ≥ 2025」,新设重点企业被单独圈出。条件以 AND 组合,由 filter_layer_data 执行。
图3 多条件过滤
步骤6 点选看详情:点击任意企业,属性框自动弹出名称、注册资本、成立日、经营范围,工商信息随点随看,无需翻库。
图4 点选详情
步骤7 龙头企业影响圈:以龙头公司为中心生成指定半径影响圈,缓冲区分析瞬间给出辐射范围。
步骤8 龙头带动能力量化:「统计影响圈覆盖几个乡镇、多少企业,汇总注册资本」,覆盖分析自动统计并给出结果——覆盖多少家、分布在哪些乡镇、注册资本合计多少,龙头带动能力被量化成一张可汇报的图。
图5 覆盖分析
步骤9 成果固化复用:「把影响圈保存为正式图层」「乡镇面转中心点」「保存场景」,分析结果沉淀为图层资产并随场景存档,下次分析从「继承」开始。
图6 场景保存与图层入库
5 代码示例:HeatmapAgent 的「感知—决策—执行—汇报」模式
热力渲染是分析链路中最常用的能力之一。下面以一个基于高德地图(AMap)的 HeatmapAgent 为例,说明智能体代码的组织方式:run() 作为总入口,内部按「感知(取数)—决策(统计与分级)—执行(渲染)—汇报(日志与状态)」四段式组织,与智能体智能体的执行范式一致。
class HeatmapAgent {
constructor(){
this.map = null; // AMap 实例
this.markers = []; // 散点覆盖物
this.heat = null; // 热力层
this.mode = 'scatter'; // scatter | heat | both
this.radius = 5; // 基础点半径
this.seed = 20261013;
this.stats = null;
}
/* —— 总入口 —— */
async run(count, seed, fit){
const t0 = performance.now();
this.setPill('running', '运行中');
this.log('感知', '读取数据源:' + fmtNum(count) + ' 个点位,' + CLUSTERS.length + ' 个聚类中心', '');
const points = this.perceive(count, seed);
this.log('决策', '强度归一化 → 5 级分档(绿/黄/紫/蓝/深紫)', '');
const plan = this.decide(points);
this.log('执行', '模式=' + this.modeLabel() + ',基础半径=' + this.radius + 'px' + (fit ? ',自适应取景' : ''), '');
const err = await this.act(plan, fit);
const cost = Math.round(performance.now() – t0);
if(err){
this.setPill('fail', '失败');
this.log('汇报', '执行失败:' + err.message, 'err');
return { ok:false, error: err.message };
}
this.stats = Object.assign(plan.stats, { cost });
this.report();
this.renderStats();
this.setPill('done', '完成');
this.log('汇报', '已完成:' + fmtNum(points.length) + ' 点 / 聚类 ' + plan.stats.clusterUsed + ' / 耗时 ' + cost + 'ms', 'ok');
return { ok:true };
}
/* —— 感知:取数(此处为模拟数据,可替换真实数据源) —— */
perceive(count, seed){
this.seed = seed;
return generatePoints(count, seed);
}
/* —— 决策:统计 + 分级 —— */
decide(points){
const levelCount = [0, 0, 0, 0, 0];
let minLng = Infinity, maxLng = -Infinity, minLat = Infinity, maxLat = -Infinity;
const clusters = new Set();
for(const p of points){
const lv = levelOf(p.intensity);
levelCount[lv.idx]++;
clusters.add(p.cluster);
if(p.lng < minLng) minLng = p.lng;
if(p.lng > maxLng) maxLng = p.lng;
if(p.lat < minLat) minLat = p.lat;
if(p.lat > maxLat) maxLat = p.lat;
}
const cLng = (minLng + maxLng) / 2, cLat = (minLat + maxLat) / 2;
const kmPerDegLng = 111.32 * Math.cos(cLat * Math.PI / 180);
const rangeKm = Math.round(Math.hypot((maxLng – minLng) * kmPerDegLng, (maxLat – minLat) * 111.32) / 2);
return { points, stats: {
count: points.length,
clusterUsed: clusters.size,
rangeKm,
center: [cLng, cLat],
levelCount,
bounds: { minLng, maxLng, minLat, maxLat },
}};
}
/* —— 执行:渲染到高德地图(演示模式走 Canvas) —— */
async act(plan, fit){
try{
if(this.demoMode){ this._demoDraw(plan); return null; }
if(!this.map) await this._initMap();
this.clearLayers();
if(this.mode !== 'heat') this._addScatter(plan);
if(this.mode !== 'scatter') this._addHeat(plan);
if(fit) this._fitView(plan.stats.bounds);
return null;
}catch(e){
return e;
}
}
async _initMap(){
await loadAMap();
this.map = new AMap.Map('map', {
zoom: 10,
center: [120.10, 36.60],
mapStyle: 'amap://styles/whitesmoke', // 浅色底图,贴近原图米色风格
});
this.map.addControl(new AMap.Scale());
this.map.addControl(new AMap.ToolBar({ position: { right: '10px', top: '10px' } }));
}
clearLayers(){
if(this.markers.length){ this.map.remove(this.markers); this.markers = []; }
if(this.heat){
try{ this.heat.destroy(); }catch(e){ try{ this.heat.hide(); }catch(e2){} }
this.heat = null;
}
}
_addScatter(plan){
const arr = [];
for(const p of plan.points){
const lv = levelOf(p.intensity);
const r = Math.max(2.5, this.radius * (0.85 + lv.idx * 0.22));
arr.push(new AMap.CircleMarker({
center: [p.lng, p.lat],
radius: r,
fillColor: lv.color,
fillOpacity: 0.82,
strokeColor: '#ffffff',
strokeWeight: 0.8,
strokeOpacity: 0.65,
zIndex: 40 + lv.idx,
}));
}
this.map.add(arr);
this.markers = arr;
}
_addHeat(plan){
this.heat = new AMap.HeatMap(this.map, {
radius: 26,
opacity: [0, 0.72],
gradient: {
0.0: '#1fae62', 0.25: '#f2b31a', 0.5: '#9c5fb8', 0.75: '#2e86de', 1.0: '#5e2f8e',
},
});
const data = plan.points.map(p => ({ lng: p.lng, lat: p.lat, count: Math.round(1 + p.intensity * 9) }));
this.heat.setDataSet({ data, max: 10 });
}
_fitView(b){
const sw = new AMap.LngLat(b.minLng, b.minLat);
const ne = new AMap.LngLat(b.maxLng, b.maxLat);
this.map.setBounds(new AMap.Bounds(sw, ne), false, [48, 48, 48, 48]);
}
/* —— 汇报:写日志与状态徽标 —— */
report(){
const s = this.stats;
$('mapBadge').innerHTML =
'<b>HeatmapAgent</b> · ' + fmtNum(s.count) + ' 个点位 / ' + s.clusterUsed + ' 个聚类' +
'<br>覆盖半径约 ' + s.rangeKm + ' km · 模式 ' + this.modeLabel() + ' · 耗时 ' + s.cost + 'ms';
}
renderStats(){
const s = this.stats;
if(!s) return;
$('stCount').textContent = fmtNum(s.count);
$('stCluster').textContent = s.clusterUsed;
$('stRange').textContent = '~' + s.rangeKm + ' km';
$('stCost').textContent = s.cost + ' ms';
}
modeLabel(){
return { scatter: '散点', heat: '热力', both: '混合' }[this.mode] || this.mode;
}
/* —— UI 辅助 —— */
setPill(state, text){
const pill = $('agentPill');
pill.classList.remove('running', 'done', 'fail');
if(state !== 'idle') pill.classList.add(state);
$('agentState').textContent = text;
}
log(tag, msg, cls){
const ln = document.createElement('div');
ln.className = 'ln' + (cls ? ' ' + cls : '');
const t = new Date().toTimeString().slice(0, 8);
ln.innerHTML = '<span class="tag">' + tag + '</span>' +
'<span class="time">' + t + '</span>' +
'<span class="msg"></span>';
ln.querySelector('.msg').textContent = msg;
$('log').appendChild(ln);
$('log').scrollTop = $('log').scrollHeight;
}
}
代码要点:perceive 负责数据源读取,本示例使用模拟数据,可替换为真实数据源;decide 完成强度归一化、5 级分档与范围统计;act 根据模式(散点、热力、混合)渲染到地图,支持自适应取景;report 输出点位数量、聚类数、覆盖半径与耗时,形成可观测的执行结果。
6 与常规 GIS 二次开发的对比
表3 常规 GIS 二次开发与智能体模式对比
|
对比维度 |
常规 GIS 二次开发 |
智能体模式 |
|
需求到成图 |
需求评审—设计—开发—联调—发布 |
对话直出,实时成图 |
|
技术门槛 |
需 GIS 与开发技能 |
自然语言即可 |
|
变更成本 |
需求变更重新排期 |
一句话调整 |
|
空间分析能力 |
需自行集成算法与算子 |
引擎内置缓冲区、覆盖分析、坐标转换等算子 |
|
成果复用 |
项目内定制,复用成本高 |
图层资产 + 场景存档,随取随用 |
|
数据接入 |
ETL、服务发布 |
文件上传解析、对话式 SQL |
|
适配对象 |
开发团队 |
业务、规划、招商一线人员 |
7 工程取舍与可观测的边界
从实现细节可以观察到几处明确的工程取舍:
渲染与入库解耦:大数据量下地图预览采用抽样渲染,入库与统计以后端全量数据为准,取舍在于交互流畅性与数据完整性的平衡;
前端暂存、显式持久化:操作配置先落前端,保存场景后才写后端,换取操作的即时可逆性,代价是需要显式提交;
字段校验兜底:通过预取字段清单约束模型输出,降低大模型幻觉对数据语义的影响,属于以确定性约束非确定性的典型做法;
歧义依赖对话澄清:当指令存在多义性(如多个同名图层实例)时,智能体需要选择或向用户确认,说明自然语言驱动在复杂指令下仍有交互成本。
在演进方向上,值得关注更大数据量下的空间索引与聚合渲染、多轮任务的执行状态管理、图层与场景的权限与数据安全治理(本节为作者基于可观测实现的分析,不代表产品承诺)。
8 结语
这场企业影响分析,从上传数据到保存场景,全流程由对话驱动完成。当「做图」不再依赖开发排期、不再要求 GIS 技能,空间分析这件事就从「工程」变成了「对话」。门槛的降低并非能力的降级——专业能力被封装进可编排的场景引擎,由智能体按需调用,这正是 AI 低代码的核心价值。
延伸阅读:
让 AI 写地图代码,装个官方技能包值不值?

