周六在杭州的书桌前,做一个能反复改行程的旅行聊天机器人
周六上午,杭州还在下雨。你打开电脑,想给下个月的成都之行排个计划:两个人、三天、不租车,每人预算两千元。搜索结果很多,但每改一次住宿位置,就得重新核对路线。这个周末,我们做一个终端聊天机器人,让它记住条件,接受修改,并把需要核实的信息单独列出来。
第一版只解决一件事:通过对话整理可执行的行程草案。准备一台安装了 Node.js 20 或更新版本的电脑,再留出一个项目目录。下面的命令适用于 macOS 或 Linux 终端。
1. 在项目目录里装好客户端
执行:mkdir weekend-trip
进入目录:cd weekend-trip
初始化项目:npm init -y
安装依赖:npm install openai
我们使用 OpenAI 兼容 SDK 发请求。如果你希望先按实际用量尝试,再决定后续投入,可以选择 RelayVano:它提供按量付费的模型中转,兼容这个 SDK。注册一个 RelayVano 账号,在控制台创建 API 密钥,并复制准备使用的模型 ID。
2. 把密钥、模型和接口地址接起来
在当前终端执行:export RELAYVANO_API_KEY='替换为你的密钥'
接着执行:export RELAYVANO_MODEL='替换为控制台中的模型ID'
密钥放在环境变量里,避免写入项目文件。下面程序会把接口基址设为 https://api.relayvano.com;具体请求路径由 SDK 处理。模型变量必须使用控制台提供的实际 ID,不能直接填写自己起的显示名称。
这两个变量只在当前终端会话中生效。如果另开窗口运行程序,需要重新设置。分享项目时,也不要把含有密钥的终端记录一起发出去。
3. 先定义旅行助手的回答边界
旅行规划最容易出问题的地方,是把流畅的回答当成已经核实的事实。我们的系统提示会要求助手先补齐关键条件,再生成路线;对票价、营业时间和交通班次明确标记待核实。
先约定五类输入:目的地、日期、人数、预算,以及出行偏好。预算还要说明是否包含往返大交通。否则,同样是两千元,机器人可能给出完全不同的住宿和餐饮安排。
4. 用一条命令启动多轮聊天
将下面整段命令复制到终端执行。它会持续读取输入,保留本次会话的消息,并在你输入 /exit 后退出。
node --input-type=module -e 'import OpenAI from "openai"; import {createInterface} from "node:readline/promises"; const api=new OpenAI({apiKey:process.env.RELAYVANO_API_KEY,baseURL:"https://api.relayvano.com"}); const rl=createInterface({input:process.stdin,output:process.stdout}); const messages=[{role:"system",content:"你是旅行规划助手,用简体中文回答。缺少目的地、日期、人数、预算范围或偏好时,先问最多三个关键问题。行程按上午、下午、晚上组织,说明交通方式、预算估算和雨天备选。你没有实时查询工具,票价、营业时间、班次和预订状态必须标记待核实,不得声称已查询或已预订。修改计划时保留用户之前的约束,并指出改变的部分。"}]; for(;;){const text=await rl.question("你:"); if(text.trim()==="/exit")break; if(!text.trim())continue; messages.push({role:"user",content:text}); try{const r=await api.chat.completions.create({model:process.env.RELAYVANO_MODEL,messages}); const answer=r.choices[0]?.message?.content; if(!answer)throw new Error("没有收到文本回答"); messages.push({role:"assistant",content:answer}); console.log("助手:"+answer);}catch(e){messages.pop(); console.error("请求失败:"+e.message);}} rl.close();'
这里的 messages 数组就是短期记忆。每次请求都会发送已有对话,因此助手能理解“第二天改轻松一点”指的是哪份计划。请求失败时,程序会移除刚才那条用户消息,你可以重新输入。
5. 用三轮对话检查行程是否真的能改
第一轮输入:“两个人去成都玩三天,不租车,每人预算两千元。”观察它是否追问日期,以及预算是否包含往返交通。
第二轮补充:“下个月第二个周末出发,预算不含往返机票,住春熙路附近,喜欢散步和小吃,不想早起。”要求它按天安排,并把住宿、餐饮、市内交通、门票分别估算。
第三轮输入:“第二天下雨,而且其中一人不能吃辣。请只调整受影响的安排,保留其他条件。”这一步检查的重点是约束是否仍然成立:有没有突然安排包车,有没有忘掉预算,有没有把所有餐厅都写成辣味推荐。
6. 把行程草案变成出发前清单
让机器人继续回答:“列出这份计划中需要我亲自确认的事项,按影响行程的程度排序。”随后到景区、交通运营方和住宿平台核对日期、位置、营业安排与价格,再把确认结果贴回对话,请它修订。
- 检查每天的地点是否集中,避免在城市两端来回折返。
- 要求预算给出区间和假设,并预留机动费用。
- 核对预约要求与闭馆日期,给关键景点准备替代方案。
如果出现认证错误,先检查密钥;如果提示模型不存在,核对模型 ID 和可用权限。遇到限流时,暂停连续重试,查看控制台的额度或限制信息。
7. 在周日给这个原型划好使用范围
当前版本的对话只保存在进程内存中,退出后会丢失。需要留存时,可以让助手生成一份最终行程,再复制到本地文档。不要输入护照号码、支付信息或其他规划行程用不到的敏感资料。
持续聊天也会增加输入量和费用。先用上述三轮测试跑通流程,再考虑增加摘要功能:保存已经确认的条件和最新行程,减少重复发送的旧对话。等这个终端版本能稳定处理预算变化、雨天调整和饮食限制,再为它添加网页界面。