From 9d891fb7028a6b0e61bf8d72be391811812ef69a Mon Sep 17 00:00:00 2001 From: kurihada Date: Mon, 2 Mar 2026 10:21:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=BA=E8=A1=8C=E7=A8=8B=E8=A7=84?= =?UTF-8?q?=E5=88=92=20agent=20=E6=B7=BB=E5=8A=A0=20get=5Ftravel=5Ftime=20?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=EF=BC=8C=E8=B0=83=E7=94=A8=E9=AB=98=E5=BE=B7?= =?UTF-8?q?=E9=A9=BE=E8=BD=A6=20API=20=E9=AA=8C=E8=AF=81=E4=BA=A4=E9=80=9A?= =?UTF-8?q?=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit agent 之前完全靠 LLM 猜测地理距离,现在可以查询真实驾车时间,超过 30 分钟会换更近地点。 同时修复 dev 端口未生效的问题(next dev 加 --port 3721)。 --- package.json | 2 +- src/lib/blindboxPlanGen.ts | 55 +++++++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index ed02c73..1a9e717 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev", + "dev": "next dev --port 3721", "build": "next build", "start": "next start", "lint": "eslint", diff --git a/src/lib/blindboxPlanGen.ts b/src/lib/blindboxPlanGen.ts index b3e9b01..75c3f87 100644 --- a/src/lib/blindboxPlanGen.ts +++ b/src/lib/blindboxPlanGen.ts @@ -195,6 +195,7 @@ export interface PlanGenResult { const AGENT_SYSTEM_PROMPT = `你是一个周末行程规划 Agent。你有以下工具可以使用: - list_ideas: 查看想法池中的所有活动 - search_poi: 在地图上搜索地点(支持品牌名、地名、品类搜索) +- get_travel_time: 查询两点间驾车时间和距离 - finalize_plan: 提交最终行程方案 规划流程: @@ -202,8 +203,9 @@ const AGENT_SYSTEM_PROMPT = `你是一个周末行程规划 Agent。你有以下 2. 根据时间、多样性、强度平衡选出合适的活动组合 3. 为每个活动 search_poi 找到具体地点 4. 如果搜索结果不理想(0结果或不相关),尝试换关键词重搜 -5. 综合地理位置、时间安排、活动特点,规划最优路线 -6. 确认无误后 finalize_plan 提交 +5. 用 get_travel_time 检查关键路段的交通时间,如果某段超过 30 分钟考虑换更近的地点 +6. 综合地理位置、时间安排、活动特点,规划最优路线 +7. 确认无误后 finalize_plan 提交 规划原则: - 地理位置相近,最小化移动距离 @@ -297,6 +299,53 @@ function buildAgentTools( }, }; + const getTravelTimeTool: AgentTool = { + name: "get_travel_time", + description: "查询两点之间的驾车预估时间和距离。用于验证活动之间的交通是否合理", + parameters: { + type: "object", + properties: { + origin_lat: { type: "number", description: "起点纬度" }, + origin_lng: { type: "number", description: "起点经度" }, + dest_lat: { type: "number", description: "终点纬度" }, + dest_lng: { type: "number", description: "终点经度" }, + }, + required: ["origin_lat", "origin_lng", "dest_lat", "dest_lng"], + }, + execute: async (args) => { + const oLat = Number(args.origin_lat); + const oLng = Number(args.origin_lng); + const dLat = Number(args.dest_lat); + const dLng = Number(args.dest_lng); + const apiKey = requireAmapApiKey(); + const url = new URL("https://restapi.amap.com/v5/direction/driving"); + url.searchParams.set("key", apiKey); + url.searchParams.set("origin", `${oLng},${oLat}`); + url.searchParams.set("destination", `${dLng},${dLat}`); + url.searchParams.set("show_fields", "cost"); + try { + const res = await fetch(url.toString()); + const data = await res.json(); + if (data.status !== "1" || !data.route?.paths?.length) { + return JSON.stringify({ error: "未找到路线" }); + } + const path = data.route.paths[0]; + return JSON.stringify({ + distanceKm: Math.round(Number(path.distance) / 100) / 10, + durationMin: Math.ceil(Number(path.duration) / 60), + }); + } catch { + return JSON.stringify({ error: "路线查询失败" }); + } + }, + progressBefore: () => "正在查询交通时间...", + progressAfter: (_args, result) => { + const r = JSON.parse(result); + if (r.error) return `路线查询失败`; + return `驾车约 ${r.durationMin} 分钟(${r.distanceKm}km)`; + }, + }; + const finalizePlanTool: AgentTool = { name: "finalize_plan", description: "提交最终行程方案。days 数组中每个元素包含 date、items(活动列表)和 summary", @@ -341,7 +390,7 @@ function buildAgentTools( progressAfter: () => "行程规划完成!", }; - return [listIdeasTool, searchPoiTool, finalizePlanTool]; + return [listIdeasTool, searchPoiTool, getTravelTimeTool, finalizePlanTool]; } async function runAgentPlanGeneration(