当前位置: 首页 > news >正文

腾讯位置服务开发者征文大赛:“独行侠”智能路线官

一个关于城市夜跑者、算法盲区与AI情感化路线推荐的真实技术实践
关键词:Go、地图SDK抽象、LLM Agent、Prompt工程、情感化推荐


目录

  • 背景需求:都市独行侠的运动品质困境
  • 痛点诊断:为什么传统地图工具"听不懂人话"
  • Module-SDK:给地图API装上"通用翻译器"
  • Module-Agent:从"指令执行"到"情绪理解"的跃迁
  • 一次完整的夜跑请求,系统在背后做了什么
  • 数据飞轮:从AI预点亮到用户共建的闭环进化
  • 共建闭环:探路者信用与路线升降级
  • 途点灯塔:让运动变成城市探索游戏
  • 写在最后

一、背景需求

随着马拉松与骑行文化的盛行,都市"独行侠"(独自运动的个体)对运动品质的要求日益提高。传统地图产品(腾讯/高德/百度)侧重于"位移效率"(最短/最快路径),忽略了运动场景下的安全舒适环境体验。用户痛点集中在:

  1. 安全焦虑:夜跑无路灯、骑行情势复杂、人车混行。
  2. 体验折损:路线拥挤(如广场舞干扰)、路面材质差(伤膝盖)、红绿灯多(打断骑行节奏)。
  3. 选择困难:想去好的路段却不知道在哪,缺乏个性化推荐。

1.1 产品愿景

构建一个AI驱动的体验优先型运动路网,让每一位独行侠都能在安全、舒适、不被打扰的环境中享受运动,并通过人机共创"点亮"城市,让孤独的汗水产生公共价值。

1.2 核心价值主张

  • 懂你的AI路线官:不止导航,更懂你的心情与体能,推荐最适合当下的路径。
  • 人机共创路网:你不再是过客,而是城市路线的"拓荒者"与"净化者"。
  • 弱PK的地缘归属:将个人运动转化为城市能量,以共建取代内卷。

二、痛点诊断:为什么传统地图工具"听不懂人话"

要解决这个问题,首先要理解传统架构的局限性。

第一层困境:算法优化目标的单一性

地图App的路线规划算法核心是最短路径、最快路径、避开拥堵。这些目标可以被精确量化,但也导致了一个盲区:所有不能被编码进权重函数的诉求都会被忽略。

"安静"怎么量化?"疗愈"怎么建模?"不想看到写字楼"怎么表达?传统架构里没有为这些维度留位置,自然也就不可能生成满足这些需求的路线。

第二层困境:推荐文案的冰冷感

即便你勉强跑完了一条路线,App给你反馈的也是"本次跑步3.5公里,配速6分12秒,消耗热量287大卡"。数据准确,但毫无温度。用户想要的不是数据报表,而是一个能理解他今晚为什么出门跑步的"同行者"。


三、Module-SDK:给地图API装上"通用翻译器"

解决第一层困境的方案,是在后端构建一个地图服务抽象层,把不同地图的差异封装在内部,对外暴露统一的服务接口。

核心设计:接口抽象 + 工厂模式

我们定义了一个MapSDK接口,把路线规划、POI搜索、地理编码等能力抽象为一组与厂商无关的方法签名:

typeMapSDKinterface{PlanRoute(ctx context.Context,req*RoutePlanRequest)(*RoutePlan,error)PlanAlternativeRoutes(ctx context.Context,req*RoutePlanRequest)([]*RoutePlan,error)SearchNearby(ctx context.Context,req*POISearchRequest)([]*POI,error)Geocode(ctx context.Context,addressstring)(*Location,error)ReverseGeocode(ctx context.Context,lat,lngfloat64)(*Address,error)Name()stringVersion()string}

配套的数据模型也彻底脱离第三方术语:RoutePlanDistanceDuration表示距离和耗时,POI用统一的Category字段描述类型。高德返回的path、腾讯返回的polyline,在各自的实现层被解析后统一写入RoutePlan.Polyline

接口的实现分散在sdk/amap/sdk/tencent/两个子包中,各自负责HTTP客户端封装、请求转换、响应解析。业务层只依赖MapSDK接口,不需要知道数据最终来自哪家厂商。

为了管理多实例生命周期,我们引入了一个带缓存的工厂:

typeSDKFactorystruct{config*Config cachemap[string]MapSDK mu sync.RWMutex}

工厂根据配置中的DefaultProvider决定默认使用哪家地图服务,同时维护一个读写锁保护的缓存映射,避免每次请求重复创建 HTTP 客户端。业务层调用factory.GetDefaultSDK()时,整个过程完全透明。

降级容错:从"单点依赖"到"多活冗余"

依赖第三方SaaS服务,容错是不可妥协的底线。我们在RoutePlanningService中实现了planWithFailover:当默认提供商失败时,自动遍历所有已注册的提供商依次重试,直到成功或全部失败。

func(s*RoutePlanningService)PlanOptimalRoute(ctx context.Context,from,to geo.Point,modestring)(*sdk.RoutePlan,error){mapSDK,err:=s.factory.GetDefaultSDK()iferr!=nil{returnnil,fmt.Errorf("获取SDK失败: %w",err)}req:=&sdk.RoutePlanRequest{From:from,To:to,Mode:mode}plan,err:=mapSDK.PlanRoute(ctx,req)iferr!=nil{returns.planWithFailover(ctx,req)// 自动降级到备用提供商}returnplan,nil}

这意味着,即使某个接口突然挂了,用户的请求也能无缝切换到腾讯继续执行,前端完全无感知。


四、Module-Agent:从"指令执行"到"情绪理解"的跃迁

SDK抽象层解决了"怎么调用地图能力"的问题,但核心难题仍未触及:系统怎么知道用户想要"安静"而不是"最快"?

答案是:让大语言模型充当"意图翻译官",把自然语言中的情感诉求转化为机器可执行的结构化约束。

可插拔LLM架构:不把鸡蛋放一个篮子里

和地图服务一样,我们不希望AI能力绑定在单一模型上。Module-Agent的LLM层采用接口抽象 + 路由器的模式:

typeProviderinterface{Complete(ctx context.Context,req*CompletionRequest)(*CompletionResponse,error)StreamComplete(ctx context.Context,req*CompletionRequest)(<-chan*StreamChunk,error)Name()string}

目前实现了腾讯混元(hunyuan-lite)、OpenAI(GPT-3.5-turbo)和本地模型的适配器,全部注册到llm.Router中。支持按默认提供商调用,也支持显式指定,为后续A/B测试和模型灰度留下空间。

更关键的是同步与流式双接口的设计:意图解析用Complete同步调用获取完整结果;对话交互场景通过 WebSocket 连接GET /api/v1/agent/stream,后端用StreamComplete逐块推送LLM生成结果,让用户看到"打字机式"的实时输出。

Prompt工程:把"黑盒"变成"可控的黑盒"

LLM很强大,但输入决定输出质量。我们把Prompt从代码中剥离,用YAML模板 + 变量替换集中管理。

以意图解析为例,intent_parser.yaml被结构化为:

system:|你是"独行侠路线官",一个资深运动向导...instruction:|请根据用户的输入,提取并推断以下寻路约束条件。 你必须严格考虑运动模式的安全特性: - 跑步:避开人车混行、主干道无隔离段output_schema:|{ "intent_analysis": { "emotion_intent": "情绪疗愈/健身锻炼/探索城市", ... }, "route_constraints": { "target_distance_km": 5.0, "must_avoid": [...], ... }, "weight_adjustment": { "safety_weight": 1.5, "quietness_weight": 1.8, ... } }examples:-user_input:"今晚想跑个5公里,要安静点的,最近工作压力大"output:|{ "intent_analysis": { "emotion_intent": "情绪疗愈", "core_demand": "低人流、环境放松" }, ... }

产品经理可以直接改YAML调整措辞、补充示例,无需重新编译后端。版本控制也让Prompt迭代可追溯、可回滚。

四维评分:让"安静"和"风景"变成可计算的量

路线评估不能凭感觉。我们设计了一套可量化的四维评分体系,每项根据用户意图动态调整权重:

维度含义典型权重
安全性人车分流比例、路灯覆盖率、夜间路况1.5x
清净度人流密度估算、远离商圈和广场舞区域1.8x
风景值沿途公园、水系、自然景观密度1.2x
路面质量塑胶/沥青/水泥路面占比与平整度1.0x

当用户说"压力大、想疗愈"时,系统自动提升清净度(1.8x)和风景值(1.2x)的权重,降低对速度效率的优先度。当用户说"想骑车探索城市"时,风景值上升,安全性保持高权重以应对骑行特殊风险。

双模切换:跑步和骑行的"画风"完全不同

PRD 中一个关键的产品设计是双模切换——顶部 Tab 切换「漫步者(跑步)」与「破风手(骑行)」。这不仅是 UI 主题色的变化(森林绿 vs 破晓橙),背后是整个算法权重的重新编排。

跑步模式的核心诉求是"护膝、清净、不被打断"。意图解析 Prompt 中明确写入约束:避开人车混行路段、优先塑胶和沥青路面、绕开广场舞聚集区。LLM 在解析"想跑五公里"时,会自动把surface_preference置为["塑胶", "沥青"],把quietness_weight拉到 1.8x。

骑行模式的核心诉求是"流畅、少停、安全隔离"。红绿灯是骑行体验的头号杀手——每等一次红灯,刚热起来的大腿就凉半截。因此骑行模式的寻路算法中,红绿灯密度被提升到与安全性同等的权重级别,traffic_light_preference强制设为avoid,同时优先选择有非机动车道隔离的路段。

这种"模式驱动权重"的设计,让我们的 Agent 不是一套通用推荐逻辑打天下,而是根据用户的运动类型,调用不同的意图解析策略和寻路参数模板。同一句话"今晚想出去动动",在跑步模式下被解读为"疗愈慢跑",在骑行模式下则被解读为"城市夜骑刷街"——推荐的目的地、路线风格、甚至文案语气都截然不同。


五、一次完整的夜跑请求,系统在背后做了什么

让我们回到小陈的场景,看看当他输入"今晚想跑5公里,要安静点的,最近工作压力大"时,系统在4秒内完成了什么。

Step 1:意图解析(LLM,约1.2秒)

intent_parser.yaml的Prompt被填充上用户输入和北京、夜晚、跑步等上下文,提交给LLM。模型返回结构化JSON:

{"intent_analysis":{"emotion_intent":"情绪疗愈","core_demand":"低人流、环境放松"},"route_constraints":{"target_distance_km":5.0,"must_avoid":["繁华商圈","广场舞区域","无路灯路段"]},"weight_adjustment":{"safety_weight":1.5,"quietness_weight":1.8,"scenery_weight":1.2,"surface_weight":1.0},"poi_preferences":["公园","水系","安静街巷"]}

Step 2:路线规划(SDK,约1.5秒)

RoutePlanningService根据约束条件,调用 Module-SDK 执行三条并行动作:

  1. 地理编码:将"家附近"转化为具体坐标;
  2. POI搜索:搜索半径2公里内的公园、水系、安静街巷;
  3. 路线规划:生成3条候选路线,分别侧重"绕公园"“沿水系”“穿静巷”。

过程中如果一方接口超时,自动降级到另一方继续执行,用户无感知。

Step 3:路线评估(LLM,约1.0秒)

三条候选路线的坐标、距离、预估清净度评分、沿途POI列表,连同用户的原始意图一起输入route_evaluator.yaml。LLM从"解析者"切换为"评审官",选出最优路线并生成推荐文案。

Step 4:返回结果(约0.3秒)

小陈的手机屏幕上出现:

推荐路线:亮马河畔静巷环线

今晚不去挤工体,带你走亮马河畔的静巷。这条线清净度拉满,听着水声慢慢跑,把工作的烦心事都丢在风里。全程人车分流很安全,1.2公里处注意下井盖。去放空吧,独行侠。

  • 安全性:4.5/5
  • 清净度:4.8/5
  • 风景值:4.2/5
  • 路面:4.0/5
  • 亮点:水系疗愈、极致清净
  • 注意:1.2km处有井盖

这不是一条"最短"或"最快"的路线,而是一条最懂他今晚为什么想出门跑步的路线。

整个流程封装在agent.Core的一个方法中:

func(a*Core)ProcessUserInput(ctx context.Context,input UserInput)(*AgentResponse,error){intent,err:=a.ParseIntent(ctx,input)// Step 1:听懂你想干什么routes,err:=a.PlanRoutes(ctx,intent,input.Context)// Step 2:去找符合条件的路线evaluation,err:=a.EvaluateRoutes(ctx,intent,routes,input.Context)// Step 3:选出最好的一条,写出推荐理由response:=buildResponse(intent,routes,evaluation)// Step 4:打包返回returnresponse,nil}

六、数据飞轮:从AI预点亮到用户共建的闭环进化

一次成功的推荐只是起点。真正的产品壁垒,在于如何让系统越用越懂用户——这需要一个持续运转的数据飞轮。

PRD 中定义的核心闭环非常清晰:AI预点亮/生成路线用户探索与体验四维打分 + 路况上报数据反哺(置信度更新/权重进化)AI推荐更精准。这个闭环回答了所有UGC类产品的终极问题:冷启动之后,内容从哪里来?

AI预点亮:冷启动期的种子路线

在产品上线初期,没有用户轨迹、没有社区验证,推荐引擎面临典型的冷启动困境。我们的策略是AI预点亮——在 seed 城市(北京、上海),基于地图路网数据和POI分布,由AI Agent批量生成一批S级和A级候选路线。

这些预生成路线带有初始置信度标签:

  • 🟢 精选:数据交叉验证充分,社区初步认证,可直接推荐;
  • 🟡 待探:AI生成,缺乏实况数据,标注"欢迎探路"标签,邀请用户验证;
  • 🔴 风险:近期差评或路况异常,隐藏或强提示。

这不是一个静态的榜单,而是会呼吸的生命体。一条"待探"路线如果被足够多的用户验证并通过,就会逐步升级为"精选";反之,一条曾经的"精选"路线如果近期因施工、路况恶化导致评分暴跌,也会被降级甚至隐藏。

用户验证:从"消费者"到"共建者"的身份转换

传统地图产品里,用户是被动消费内容的角色——打开App,搜索,跟随导航,结束。但在 Map Games 的设计中,每一次运动完成后,用户都会被邀请参与共建:为刚才跑过的路线进行四维打分、上报途中发现的路况问题。这种设计让个人运动数据产生了公共价值,用户不再只是"过客",而是城市运动路网的"拓荒者"与"净化者"。

这个身份转换的心理价值不容忽视。当一个人知道他的打分会影响后续 thousands of runners 的路线选择时,他会更认真地回忆刚才那段路上的路灯够不够亮、路面有没有坑。这种微小的责任感,是UGC内容质量的第一道防线。


七、共建闭环:探路者信用与路线升降级

数据飞轮要跑起来,需要一套可信的评分和升降级机制。否则,刷分、恶意差评、随机打分都会让置信度体系崩塌。

四维滑块打分:把主观体验变成结构化数据

运动结束页会弹出四维滑动条,用户用1-5分(0.5步长)为刚才的路线打分:

  • 🛡️ 安全感:路灯够不够?车流大不大?
  • 🍃 清净度:有没有广场舞大妈?有没有施工噪音?
  • 🌲 风景值:沿途有没有公园水系?还是全是写字楼围墙?
  • 🛣️ 路面质:塑胶跑道还是碎砖烂路?膝盖疼不疼?

这四项评分通过后端实时回传,直接参与路线置信度的加权计算。

快捷路况上报:人人都是路况传感器

除了打分,我们还提供了一组标签式上报按钮:[施工] [坑洼] [逆行] [野狗] [无灯]。用户不需要写长文描述,点击即提交。后端将上报内容与轨迹片段绑定(不包含用户ID),作为路况热图的数据源。

探路者信用分:让认真的人更有话语权

这里隐藏着一个关键的反作弊设计——探路者信用分。系统根据用户的历史活跃度(运动频次)、打分一致性(是否总是极端分)、以及上报真实性(与后续其他用户上报的交叉验证),为每个用户计算一个隐形的信用分。

高信用用户的打分会获得1.5x 到 2x 的权重加成。这意味着一个经常跑步、打分规律、上报准确的"老炮",他的一次四维度评分,可能抵得上三个新用户的随机打分。这个设计在不暴露算法细节的前提下,用博弈论机制激励了真实、持续的高质量UGC。

路线升降级:社区自治的算法实现

后台有一个定时任务,定期扫描所有路线的评分数据:

  • 一条路线如果积累超过50人打分,且均分超过4.0,🟡待探自动升级为🟢精选,进入城市金路线榜;
  • 反之,如果近期均分跌破3.5,曾经的🟢精选会被降级为🔴风险,从推荐列表中隐藏。

这套规则看似简单,但实际上构成了一个社区自治的算法实现:不是产品经理决定哪条路线值得被推荐,而是真实跑过这条路的人用他们的汗水和评分投票。


八、途点灯塔:让运动变成城市探索游戏

如果只有路线和数据,运动依然是枯燥的。我们需要一种方式,把一条线性的跑步轨迹变成一段有节点、有惊喜、有成就感的探索旅程。

途点设计:从"景点"到"心流里程碑"

PRD 中定义了三种途点类型,沿途标注在路线上:

  • 🏞 风景点:河边、公园、观景点——让你在疲惫时抬头就能看到值得停下来的理由;
  • 🔥 挑战点:坡顶、长坡段——用"击败这段坡"的成就感对抗放弃的念头;
  • 🧭 特殊点:城市边界、历史地标——把运动变成认识城市的媒介。

MVP 阶段我们为每个城市预置了至少100个途点。这些途点不是地图上已有的POI,而是基于运动体验重新设计的"心流里程碑"——它们的存在不是为了提供信息,而是为了在正确的时机给用户一个情绪锚点。

无感打卡:不打扰的仪式感

传统打卡需要用户掏出手机、打开App、点击按钮。对跑者而言,这意味着打断节奏、影响心率。我们的设计是GPS无感自动触发:当系统检测到用户进入途点半径20米范围内,自动完成打卡,语音播报"已点亮亮马河观景点"。

这种"不强制停留、不主动操作"的设计,尊重了运动状态的连续性。但它依然创造了仪式感——当用户跑完一段路线,回顾轨迹时发现沿途亮起了三个"已点亮"的途点标记,那种"探索地图"的成就感,是传统运动App的"本次跑步3.5公里"无法比拟的。


九、写在最后

Map Games 项目目前完成了 Module-SDK 的核心功能(路线规划、POI搜索、地理编码、降级容错)和 Module-Agent 的 Phase 1(多LLM支持、意图解析、路线评估、HTTP/WebSocket双接口),以及数据飞轮与共建闭环的初步设计。整体完成度约60%。

回顾这个项目的技术路径,我们始终在做一件事:把"不能被传统算法量化"的用户诉求,通过LLM转化为"可以被工程系统执行"的结构化约束。地图SDK的抽象层解决了底层能力的可插拔问题,Agent工作流解决了意图理解的问题,数据飞轮解决了冷启动后内容持续进化的问题。三者叠加,构成了一个从"听懂用户"到"服务用户"再到"与用户共建"的完整闭环。

接下来的重点包括:基于腾讯地图Skills文档增强SDK能力(沿途搜索、距离矩阵);Flutter前端对话界面与双模切换UI的完整实现;以及Redis缓存、LLM响应缓存、Prompt持续调优。

如果你也在做类似的智能地理应用,或者在思考怎么让LLM真正"落地"到垂直业务里而不是停留在Demo层面,希望这篇实践能给你一些启发。特别想听听大家的想法:

你觉得地图服务还能和哪些AI能力结合?除了跑步场景,通勤、骑行、Citywalk还有哪些情感化需求被现有产品忽视了?共建闭环里的信用分机制,你觉得还有哪些反作弊策略值得尝试?

欢迎在评论区留言讨论。觉得有启发的话,点个赞或者转发给正在做相关项目的朋友——你的每一次互动,都是我们继续分享技术实践的最大动力。

http://www.jsqmd.com/news/800023/

相关文章:

  • 功能开关与远程配置:现代Web应用安全发布与动态控制实践
  • 防爆风机哪家好?2026高温风机厂家推荐:离心风机/高压风机生产厂家+防腐风机厂家合集 - 栗子测评
  • 别再乱写SDC了!ICC II里Mode、Corner、Scenario约束文件分离的实战技巧与内存优化
  • IrDA OBEX文件传输技术解析与Microchip实现
  • 热电模块技术原理与PCR温度控制应用
  • selection.js:简化DOM文本选区管理的轻量级JavaScript库
  • 轻量级GraphRAG实现:nano-graphrag核心原理与定制指南
  • Viterbi 算法直接用在中文分词上
  • 别再乱调了!大漠模块SetKeypadDelay/SetMouseDelay参数详解与实战避坑(易语言)
  • 第二章-05-目录切换相关命令(cd/pwd)-课后练习
  • Gemini辅助写周报/月报:从零散记录到结构化汇报的提效方法.
  • 3大维度重构游戏体验:DOL汉化美化整合包全指南
  • 2026 Git 高频面试攻坚:从底层原理到企业级救火(进阶实战版)
  • 嵌入式软件架构一:一个能让人放心接手的嵌入式项目,骨架长什么样
  • MinerU 实战训练营:RAG 数据预处理的最后一块拼图
  • 阿里:时序课程解决多轮蒸馏不稳定
  • 手把手调SVPWM:如何根据你的直流母线电压Udc设置正确的调制比不炸管?
  • 从关中到汉中:用Python+DEM数据,分析古代行军路线的地理可行性
  • Awesome List自动化生成:从手工整理到工业化生产的效率革命
  • 健身直播必备:手表心率如何实时显示在手机拍摄画面上?
  • YOLO26引入Dual-ViT自注意力:局部与全局两条主线的完美交汇
  • 基于Agent-Next框架的Polymarket预测市场模拟交易系统构建指南
  • 告别重复劳动:手把手教你用SAP LSMW为MM模块创建第一个数据导入程序
  • 四轴飞行器入门:BNO055与JY901传感器模块选型及实测对比
  • 2026年4月国内知名的数字化服务平台源头厂家推荐,KYN28-12铠装移开式金属封闭开关柜,数字化服务平台公司哪家好 - 品牌推荐师
  • TinyML实战:tiny-ai-client在MCU上的轻量级AI推理部署指南
  • 效率翻倍!依据2026白皮书,这样部署OpenClaw最快(移动云电脑版)
  • 别再死记硬背了!用Python+NumPy图解NCHW与NHWC,彻底搞懂数据排布
  • C++ 入门核心语法|从 Hello World 到基础特性一次性吃透
  • HIOKI-3272 日置 3272 电源 用于3273-50 3274 3275 3276探头