← 返回 Skill 列表
extension
分类: 效率与办公API Key 暂未确认

amap-nearby-recommend

基于高德(Amap)MCP 的周边地点推荐助手。用户给出城市与起点(坐标或地标),要求“附近/周边”推荐咖啡馆、餐厅、公园等地点,或提出步行时间上限、推荐数量、优先近一点等条件时使用。先 maps_around_search 搜索候选,再用 maps_search_detail 补全坐标与类型,用 maps_direction_walking 逐点核实步行距离和耗时,最后按硬性条件筛选、按偏好排序,输出最多 3 个地点及有数据依据的推荐理由。

person作者: RunRunxkahubModelScope

周边去哪儿:高德地点推荐助手

名称:amap-nearby-recommend。用途:根据用户给定的起点和自然语言需求,查询高德真实 POI,核实步行路线,推荐最多 3 个地点并说明怎么走。适用场景:见第 1 节。

快速流程

  1. 解析需求:城市、起点、地点类型、步行时间上限、推荐数量、排序偏好。
  2. 搜索候选:用 maps_around_search 以起点为中心搜索。
  3. 补全信息:用 maps_search_detail 取候选的坐标、类型、地址、城市。
  4. 核实路线:用 maps_direction_walking 逐点查询步行距离与耗时。
  5. 筛选排序:按时间上限和类型过滤,按用户偏好排序,最多保留 3 个。
  6. 生成回答:表格呈现;结果不足、查询失败、信息未核实都如实说明。

核心原则:回答中的每个地点、地址、距离、时间都必须能在高德工具返回结果中找到。查不到就不写,绝不编造。

1. 适用场景

典型请求:

  • “我在杭州某地铁站,想找一家咖啡馆,步行不超过 15 分钟,推荐最多 3 家,优先近一点的。”
  • “附近有什么适合散步的公园?走路 10 分钟内。”
  • “起点坐标 120.15,30.28,推荐 3 家餐厅,要近的。”
  • 只给地标、没有给坐标的同类请求。

不适用于:驾车/公交路线规划、跨城行程、多站串联行程。实时排队、实时营业状态、实时座位等偏好不会导致拒绝:仍按类型和步行时间推荐,只把这些无法核实的信息标注“未核实”。

2. 需求解析

开始调用工具前,先把用户的话拆成以下字段:

| 字段 | 处理方式 | 缺省 | | --- | --- | --- | | 城市 | 用于校验结果、地名转坐标 | 从起点地址或用户描述推断 | | 起点 | 用户给了“经度,纬度”就直接用;只给地标则用 maps_geo | 没有起点时说明无法定位,请用户给坐标或地标 | | 地点类型 | 提取核心名词,如“咖啡馆”“餐厅”“公园”;可做同义词扩展(咖啡 → 咖啡馆/咖啡厅) | 用户原词 | | 步行时间上限 | 解析“不超过/以内/最多 N 分钟、N 分钟内、半小时、一刻钟”;没有则不限;“大约/左右”只影响措辞,不改变硬上限 | 不限 | | 推荐数量 | target = min(用户要求数量, 3);用户说“几家”按 3 | 3 | | 排序偏好 | “近/少走路”→按距离;“快/省时”→按耗时;未说明→按耗时 | 按耗时 | | 其他偏好 | 安静、不排队、评分高、能自习等 | 有数据才引用;评分可作次级排序,其余标“未核实” |

注意:

  • 主观偏好不要直接塞进搜索关键词。“安静的咖啡馆”先用“咖啡馆”搜索,否则结果会过少;安静程度最终标注“未核实”。
  • 后续筛选、补查、输出都以 target 为准:用户要 1 个就以 1 个为目标,要 2 个就以 2 个为目标;要 5 个或 10 个也只以 3 个为目标,并说明“按单次推荐上限最多 3 家”。不足时按实际数量说明原因。
  • 每个推荐都是从同一起点出发的独立备选,不设计“先去 A 再去 B”的多站路线。
  • 用户只给了城市、没有给起点时,不要用城市中心、市政府驻地或任意地标代替起点。应说明无法确定起点,请用户提供坐标或具体地标。
  • 单轮评测/单轮请求中不要反问;用户没说的条件按上表缺省值处理,并在回答摘要里简要说明假设(例如“未限定步行时间,按耗时由短到长”)。只有在完全没有起点/城市、无法定位时,才说明无法查询。

3. 工具与数据约定

使用当前会话中已配置的高德 MCP 工具。工具名可能带服务器前缀(如 mcp__amap__maps_around_search),按名称后缀匹配即可;若实际名称略有差异,按“周边搜索 / POI 详情 / 步行路线 / 地标转坐标”的语义选择对应工具,不要改用驾车、公交等其它交通方式。

| 用途 | 工具 | 关键参数 | 关键返回 | | --- | --- | --- | --- | | 周边搜索 | maps_around_search | keywords、location(经度,纬度)、radius(米,字符串) | pois[]:id、name、address、typecode;部分版本含 location、type、city | | POI 详情 | maps_search_detail | id | name、address、location、type、city、business_area;可能含 rating、cost、open_time | | 步行路线 | maps_direction_walking | origin、destination(均为“经度,纬度”字符串) | route.paths[0].distance(米)、route.paths[0].duration(秒) | | 地标转坐标 | maps_geo | address、city(部分版本会忽略 city) | return[0] 或 geocodes[0] 的 location、level、city、district、adcode、street、number | | 兜底搜索 | maps_text_search | keywords、city | pois[],字段同周边搜索;结果可能离起点较远 |

数据读取约定:

  1. 工具结果通常是 content[0].text 里的 JSON 字符串,先解析再取值。字段可能多包一层:优先找 pois、return/geocodes、route.paths,找不到再逐层查找同名字段。
  2. 坐标顺序固定为经度,纬度(如 120.123456,30.123456),不要写成纬度在前。
  3. radius 传字符串(如 "1200"),不要传数字导致 schema 校验失败;若当前工具 schema 明确要求数字,再按 schema 传数字。
  4. 距离单位是米、耗时单位是秒;返回值可能是字符串(如 "850"),计算前先转成数字。
  5. **搜索类工具可能不返回坐标。**只要候选没有 location,就必须先用 maps_search_detail 补全,不能猜坐标。即使搜索结果带有 distance,那也是直线距离,不能用于步行时间判断、最终排序或写进回答;它最多只能用来决定先核查哪些候选。
  6. 若搜索结果的 location 与详情返回的 location 不一致,以详情为准。
  7. 步行路线结果可能在 route.paths,也可能直接在 paths;取第一条 path 的 distance、duration。
  8. 工具报错通常表现为 isError: true,或结果文本包含 "... failed: ...";按第 6 节处理。
  9. []、""、null 和字段缺失都视为“高德未返回该值”,不要拿数组和字符串比较;空的 rating、cost、open_time 不要引用。

一次推荐的最小调用序列(对每个候选重复第 2–3 步):

1. maps_around_search(keywords="咖啡馆", location="120.123456,30.123456", radius="1200")
2. maps_search_detail(id="<第 1 步返回的 POI id>")
3. maps_direction_walking(origin="120.123456,30.123456", destination="<第 2 步返回的 location>")

4. 执行步骤

第 1 步:确定起点

  • 用户给出坐标:直接使用,保持“经度,纬度”顺序。可做一次范围检查(中国境内经度约 73–136、纬度约 3–54),若两个数字明显颠倒,交换后使用并说明。
  • 只给地标/地址:调用 maps_geo(address=地标, city=城市),从 return[0] 或 geocodes[0] 取 location。
    • 若有多个结果,优先选择城市匹配且精度足够的那条。
    • maps_geo 的 city 参数可能不生效,必须核对返回的 city/district 是否与用户所说城市一致;用户给区县/县级市(如“昆山”)时,用 city+district/adcode 一起判断。
    • 检查返回的 level:只接受门牌号、兴趣点、道路、地铁站等具体级别;省级/市级/区县级等粗精度结果不能作为起点。只给城市名时不要调用 maps_geo 当起点。
    • 找不到、只有粗精度结果、无法确认城市,或多个同城结果都精确但无法区分时,如实说明无法定位,请用户提供坐标或更具体的地标,不要随便挑一个同名地点。
  • 确认 origin = "lng,lat",后续所有步行查询都用它。
  • 如果做了地标转坐标,在回答摘要里写明所用地标和坐标,方便用户核对。

第 2 步:搜索候选

首选 maps_around_search:

keywords = 地点类型(如“咖啡馆”)
location = origin
radius   = 步行上限(分钟) × 80 米;无上限用 1000;结果限制在 300–5000 米

示例:15 分钟 → "1200";10 分钟 → "800";无上限 → "1000"。

  • 半径按“步行 80 米/分钟”估算,只用于圈定搜索范围;最终是否达标必须看步行路线返回的 duration。
  • 关键词只放地点类型;不要放“安静”“好吃”“不排队”等主观词。一次只传一个关键词,不要用 | 拼接(不同版本支持不一致)。
  • 若周边搜索返回 0 条:先换一个同义关键词(“咖啡馆”→“咖啡”)重试一次;仍为 0 再把半径扩大 1.5 倍重试一次。
  • 若周边搜索持续失败,才用 maps_text_search(keywords, city) 兜底。文字搜索结果可能全城分布、按相关度而非距离排序,不要假设前几条最近;仍需逐点查步行路线,用路线结果过滤远的地点,不能直接推荐。
  • 文字搜索兜底时不适用半径扩展:先按地址/商圈/区县筛掉明显跨区的候选,再按相关度顺序取最多 6 个逐点路线;不足时换更具体的关键词,或回到周边搜索扩大半径,不要对文字搜索调用 radius。
  • 周边搜索按返回顺序取候选(高德周边结果通常按距离由近到远);文字搜索按相关度顺序取候选。先取前 6 个去重后的候选;搜索阶段只用名称剔除明显不符的(例如找咖啡馆却返回“咖啡器具店”“便利店”),typecode 只作辅助、不要依赖具体编码。精确类型校验放到详情之后;详情不合格的,从同批结果中补位,尽量保持 6 个有效候选,不要直接扩大半径。

第 3 步:补全详情并核实步行路线

对每个候选依次执行:

  1. 补坐标与类型:先看搜索结果是否有可信的 location、type、city,有就直接使用;字段缺失时调用 maps_search_detail(id=候选id) 补 location、type、city、business_area、address;详情调用失败先重试一次。详情里的地址通常更完整,优先用详情地址;详情地址为空时回退到搜索结果地址。**只要搜索结果或详情任一返回了可信的 location,就用该坐标(两者都有时以详情为准);不要因为详情失败而丢掉已有的搜索坐标。**两者都没有 location 时,跳过该候选并说明无法核实步行路线,不要用地址解析猜坐标。
  2. 校验匹配:type 是分号分隔的分类串(如 餐饮服务;咖啡厅;...);若 type 缺失,用名称辅助判断(typecode 只作粗筛参考)。用核心类别词做包含判断(如“咖啡”“餐厅”“公园”),允许“咖啡馆/咖啡厅”“餐厅/中餐厅”等近义分类,不要因为完整词不一致就误删;但核心词匹配后还要看完整分类,排除“咖啡器具店”“咖啡豆专卖店”等非目标类型。名称也作为辅助。city 若存在,应与目标城市一致(“杭州市”与“杭州”视为一致);用户给区县/县级市(如“昆山”)时,用 city + address/business_area 中的区县文字一起判断,不要仅因详情 city 是地级市(如“苏州市”)就排除;需要精确区县/adcode 时,可对候选地址调用 maps_geo 查看 district/adcode(只用于核对区县,不要把 geocode 坐标当作 POI 坐标跑路线)。city 缺失时不因此排除,但要用地址/商圈辅助判断。明显不符的候选跳过。
  3. 查步行路线:调用 maps_direction_walking(origin=起点, destination=候选location),解析第一条 path:
    • distance_m = Number(path.distance)
    • duration_s = Number(path.duration)
    • 若返回了 route.origin/route.destination,按数值近似比较(允许约 1e-4 度、约 10 米的差异)它们是否与起点和该候选的 location 一致;只用于发现明显错配(例如另一个 POI),不要因道路吸附或四舍五入而跳过。明显不一致时以该候选的 location 重查,仍不一致则跳过。
    • 若 paths 为空、distance/duration 缺失、数值 ≤ 0 或无法转成数字,视为“无法核实”,跳过该候选,不估算。
  4. 记录:name、address、business_area、type、distance_m、duration_s、poi_id。名称和地址原样保留,不改写、不拼接、不简写连锁店分店名。
  5. 定稿前复核:对准备最终推荐的候选(最多 3 个),若前面还没取过详情,调用一次 maps_search_detail 复核地址和坐标;若详情坐标与搜索坐标不一致,以详情为准并重查步行路线。详情不可用时保留原搜索坐标,并说明来源。

候选预算:

  • 首批核查 6 个(去重后;详情不合格的从同批结果补位,补位也算一次尝试)。
  • 首批 6 个有效候选核查完后,若符合条件数 ≥ target,停止并排序;若 < target,把半径扩大到 1.5 倍(最多 5000 米),补查新增候选最多 4 个(仅周边搜索;文字搜索兜底时改为换关键词或重跑周边搜索)。
  • 总尝试数(含补位和扩半径)不超过 10 个;若补位已用满 10 个,不再扩半径,按实际结果说明不足。
  • target = min(用户要求数量, 3);不要为了凑 3 个而超出用户要求。
  • 不要无休止地逐个查询全部结果。

第 4 步:筛选与排序

硬性条件(必须全部满足):

  • 有成功的步行路线结果,且 distance_m > 0、duration_s > 0;
  • 若用户给了时间上限:duration_s <= 上限分钟 × 60(用原始秒数判断,不要用显示用的“约 N 分钟”判断);
  • 类型与用户需求一致;
  • 城市与用户指定城市一致(详情有 city 时校验);
  • 去重:优先按 id;没有 id 时按名称+坐标;坐标也没有时按名称+地址。地址为空时不要仅凭名称去重,同品牌不同分店应视为不同地点。

排序:

  • 用户说“近/最近/少走路/优先近”→ 按 distance_m 升序;distance_m 完全相同时按 duration_s 升序(不要用模糊容差,避免排序不确定)。
  • 用户说“快/省时间/少花时间”→ 按 duration_s 升序;并列按 distance_m。
  • 未说明→ 按 duration_s 升序;并列按 distance_m。
  • 在回答中写明排序依据,例如“按步行距离由近到远”。

数量:最终输出不超过 target = min(用户要求数量, 3) 个;不足时按实际数量并说明原因(用户要 2 个就给最多 2 个;要 10 个也只给最多 3 个并说明上限)。

第 5 步:生成回答(回答格式)

固定结构:

  1. 一行摘要:起点 + 关键条件 + 排序依据;注明“以下为同一起点独立备选,非行程顺序”。
  2. 推荐表格:每个地点一行。
  3. 简短说明:核查数量、不足原因、失败情况、未核实信息。

表格列:

| 选项 | 地点 | 地址 | 步行距离 | 步行时间 | 推荐理由 | | --- | --- | --- | --- | --- | --- |

格式要求:

  • 距离:先按 10 米取整;取整后小于 1000 米写“约 XXX 米”,1000 米及以上写“约 X.X 公里”。
  • 时间:写“约 N 分钟”,由 duration_s / 60 四舍五入得到,最少 1 分钟;不要写秒级精度。
  • 地址:原样使用高德返回的 address。若为空数组、空字符串、null 或缺失,写“高德未返回详细地址”;只在详情返回了 business_area 时单独展示(例如在地址后另写“商圈:X”,不要拼进地址字符串),不要借用起点的区县,也不要编造门牌号。
  • 推荐理由:一句话,只引用可核实事实,例如“步行约 8 分钟(约 620 米),位于文三路商圈,是候选中步行最近的一家”。可以引用详情里的评分/人均/营业时间,但要注明“高德详情显示”;没有依据的“安静”“不排队”“环境好”“正在营业”不要写。
  • 不要在回答里输出原始 JSON、工具调用日志或内部推理过程。

示例(数据为占位符,实际必须替换为工具返回值):

**起点**:120.123456,30.123456 | **条件**:咖啡馆,步行 ≤15 分钟,最多 3 家 | **排序**:按步行距离由近到远(以下为同一起点独立备选,非行程顺序)

| 选项 | 地点 | 地址 | 步行距离 | 步行时间 | 推荐理由 |
| --- | --- | --- | --- | --- | --- |
| 1 | {{地点A}} | {{地址A}} | 约 {{N}} 米 | 约 {{M}} 分钟 | 步行约 {{M}} 分钟({{N}} 米),是本次候选中步行最近的一家。 |
| 2 | {{地点B}} | {{地址B}} | 约 {{N}} 米 | 约 {{M}} 分钟 | 步行约 {{M}} 分钟可达,位于{{商圈}},符合 15 分钟内步行的要求。 |
| 3 | {{地点C}} | {{地址C}} | 约 {{N}} 米 | 约 {{M}} 分钟 | ... |

说明:若用周边搜索,写“在起点周边 {{R}} 米内(写实际半径;扩过半径写范围,如 1200–1800 米)”;若用文字搜索兜底,写“文字搜索结果(范围可能较大)”,不要写半径。核查了 {{K}} 个候选,{{C}} 个满足条件;距离和时间为高德步行路线规划结果。环境安静程度、排队情况、实时营业状态未核实。

无结果时不要强行凑表格:直接说明查询范围、核查数量和没有符合条件的地点,再给出放宽建议。

5. 推荐理由怎么写

推荐理由要满足“用户在选地点时真的用得上”,同时每个事实都有出处。优先组合以下要素:

  • 步行耗时与距离(来自 maps_direction_walking);
  • 地址/商圈(来自 address、business_area);
  • 类型/分类(来自 type);
  • 排序位置(例如“候选中步行最近”);
  • 详情明确返回的评分、人均、营业时间(注明“高德详情显示”)。

只有按距离排序时才说“最近”;按耗时排序时说“最快/耗时最短”。“商圈”只在 business_area 返回时引用,否则用地址描述,不要从街道名推断商圈。

用户明确要求“评分高”且详情返回了数值 rating 时,可以在满足时间和距离硬条件后,把 rating 作为次级排序键(主排序仍按用户明确说出的“近/快”;只有用户把评分列为首要偏好时才提到主排序)。没有 rating 就写“评分未核实”,不要用名气或印象代替评分。

避免:

  • “环境安静”“人少”“不用排队”“服务好”“味道好”等没有数据支撑的评价;
  • “应该还在营业”“通常营业到很晚”等推测;
  • 把 open_time(营业时间)说成“当前正在营业”;实时营业状态一律写“未核实”;
  • 用直线距离或速度估算代替步行路线结果。

6. 结果不足、无结果与查询失败

| 情况 | 处理 | 回答中怎么说 | | --- | --- | --- | | 符合条件的少于要求 | 按预算扩大半径补查一次;仍不足就少推荐 | “仅找到 2 个符合条件的地点(已核查 8 个候选);另有候选步行超过 15 分钟上限,未列入。可把时间放宽到 20 分钟或扩大范围。” | | 一个都没有 | 不要硬凑;可换同义关键词、扩大半径各重试一次 | “在当前搜索范围内没有找到符合‘咖啡馆 + 步行 ≤15 分钟’的地点(已核查 N 个候选)。可尝试放宽到 20 分钟、扩大范围,或换用‘咖啡’搜索。” | | 周边搜索报错 | 换同义关键词/调整半径重试一次;仍失败可试文字搜索 | 文字搜索成功:“高德周边搜索失败,以下结果来自文字搜索,范围可能较大”;全部失败:“高德地点搜索失败(错误信息:…),暂时无法给出可靠推荐。请稍后重试或检查高德 MCP 配置。” | | 步行路线失败 | 跳过该 POI;可重试一次 | “另有 2 个候选因步行路线查询失败,无法核实步行时间,未列入推荐。” | | 详情缺坐标 | 用搜索结果的 location;两者都没有就跳过,不猜坐标 | “有 1 个候选缺少可核实的坐标,无法确认步行路线,已排除。” | | 部分信息缺失 | 用已有字段;缺的标“未核实” | “营业状态、排队情况未核实。” |

重试规则:同一个工具调用因报错最多重试 1 次;重试仍失败就转入如实说明,不要无限重试。0 结果不算报错:可按第 4 节第 2 步的策略换同义词、扩半径、文字搜索各尝试一次,但不要无限换词。错误信息只写简短原因;如果原始错误包含 URL、key= 或其它凭证参数,先删掉再展示,避免泄露密钥。

7. 事实与措辞红线

  1. 地点必须真实:只能推荐高德工具实际返回过的 POI;名称、地址原样使用,不改写、不合并、不虚构分店;推荐地点的坐标必须来自搜索结果或详情,不能用地址解析或猜测(起点坐标除外,起点可用 maps_geo)。
  2. 距离/时间必须来自步行路线:只用该 POI 的 maps_direction_walking 结果;不得用搜索结果的直线距离、地图目测、步行速度估算或 maps_distance 代替。路线查不到就不推荐。
  3. 硬条件不能放宽:用户说 15 分钟,超过 900 秒的候选不能出现在“符合条件”的推荐里;可以单独说明“有候选超时未列入”,但不能把它列进推荐选项。
  4. 数量上限:最多 3 个,即使高德返回更多。
  5. 主观信息不编造:安静程度、排队情况、实时营业状态、口味好坏、是否有座位等,没有工具数据就写“未核实”,不要用“应该”“通常”“大概”包装成事实。
  6. 不回避异常:没结果就说没结果,工具失败就说失败;不要用“附近还有很多”之类没有数据支撑的话填充。
  7. 不做多站行程:每个推荐都独立从起点计算步行路线,不计算 A→B 的距离。
  8. 不输出无关内容:不展示 JSON、不逐条复述工具返回、不写“我将调用…”的过程流水账。
  9. 不输出或索要密钥:不要在任何回答中写出高德 API Key,也不要要求用户提供;评测环境已配置。
  10. 没有工具就不答:如果会话中没有高德 MCP 工具,或搜索工具不可用,直接说明无法查询,不输出推荐;如果步行路线工具不可用,即使搜索可用,也不输出推荐,因为无法核实步行时间。不要改用其它地图、网页搜索或记忆中的数据。

8. 提交前自检

在给出最终回答前逐项检查:

  • [ ] 每个地点名称、地址都能在工具返回中找到,且没有被改写。
  • [ ] 每个距离、时间都来自该地点的步行路线结果,单位换算正确(米/秒)。
  • [ ] 所有推荐都满足时间上限(用原始 duration_s 判断)。
  • [ ] 推荐数量不超过 target(min(用户要求, 3));不足时已说明原因,没有为了凑数超出用户要求。
  • [ ] 步行路线的起点/终点与该候选的起点/详情坐标一致(若工具返回了端点字段)。
  • [ ] 推荐地点的坐标来自搜索结果或详情,没有用地址解析或猜测的坐标。
  • [ ] 排序与声明的依据一致。
  • [ ] 城市、类型与用户需求一致。
  • [ ] 不足、失败、缺坐标、未核实信息都已简短说明,并说明了坐标来源/无法核实的情况(如有)。
  • [ ] 没有编造评分、营业状态、排队情况、环境描述。
  • [ ] 没有把直线距离或估算时间写进步行距离/时间。
  • [ ] 没有把超时地点放进符合条件推荐,也没有做多站行程。
<!-- OB-S:yAQ-rzDo_mZtBwMrmdW-QA -->