京言AI助手晚上点烧烤深度测评:速度、口味与性价比全面解析
我们以晚间通过京东App内置的京言AI助手订购外卖为实战场景,完整演示LLM、工具、记忆、规划四大模块的协同闭环。假设京东App已集成智能助手(类似“京言AI助手”),用户向该助手发出以下指令:
以下为完整的执行链路,严格对应你给定的典型循环流程(理解 → 规划 → 读记忆 → 调工具 → 存记忆 → 回复)。
1. LLM 接收并解析用户指令
原始输入为自然语言,需提取核心意图(点外卖)、约束条件(辣、少油)、平台限定(京东外卖)、执行动作(选店并下单)。
LLM 的关键操作:识别关键要素——晚上(时段暗示)、辣的(口味偏好)、不要太油(健康诉求)、京东外卖(指定工具)、直接下单(行动指令)。同时明确缺失信息:用户当前位置、具体店铺、菜品、支付方式(但可能从记忆模块补全)。输出结构化意图:{ action: "order_food", cuisine: "spicy", oil_level: "low", platform: "JD_Food", auto_confirm: true }
2. 规划模块分解任务
规划模块依据当前状态(已有意图、缺失信息)生成可动态调整的执行计划。典型计划如下:
步骤 |
动作 |
所需模块 |
说明 |
|---|---|---|---|
1 |
读取用户长期记忆 |
记忆 |
获取默认地址、历史口味偏好、常用支付方式 |
2 |
获取实时位置(若记忆中无地址或用户移动) |
工具 |
调用京东App的GPS定位接口 |
3 |
查询京东外卖API,获取附近餐厅及菜品 |
工具 |
传入位置、关键词“辣 低油”,返回候选列表 |
4 |
让LLM评估候选结果,选择最佳餐厅和菜品 |
LLM |
结合“辣但不油”约束和记忆中的历史评分 |
5 |
调用下单API |
工具 |
传入餐厅、菜品、地址、支付方式 |
6 |
将订单信息写入长期记忆 |
记忆 |
记录本次消费,用于未来推荐 |
7 |
生成自然语言回复 |
LLM |
告知用户下单结果 |
3. 记忆模块提供上下文
在步骤1执行时,记忆模块被查询。它分为两部分:
短期记忆(本次会话):用户刚说的“晚上、辣的、不要太油”。尚未完成的下单操作状态。
长期记忆(跨会话存储,通常用向量数据库或键值表):
default_address: "北京市朝阳区XX小区12号楼302"
payment_method: "京东白条"
food_history: [ { date: "2025-10-01", item: "麻辣香锅(少油)", liked: true }, { date: "2025-10-05", item: "辣子鸡", feedback: "油太大" } ]
preferred_cuisine: "川菜", "湘菜"
记忆模块将这些信息返回给LLM和规划器,供后续步骤使用。
4. LLM 决定调用工具(第一次:查询外卖)
LLM 读取短期记忆中的计划步骤3:需要调用 京东外卖查询工具。
工具名称:search_jd_food
参数:
{"location": "北京市朝阳区XX小区12号楼302","keywords": ["辣", "少油"],"radius_km": 3,"max_results": 5}
工具返回结果(存短期记忆):
[{ "store": "川西坝子·少油麻辣香锅", "distance": "800m", "rating": 4.8, "dishes": [{"name": "招牌少油香锅", "spicy": true, "oil_level": "low", "price": 38},{"name": "微辣牛肉卷", "spicy": true, "oil_level": "medium", "price": 32}]},{ "store": "湘遇·低油菜馆", "distance": "1.2km", "rating": 4.6, "dishes": [{"name": "少油小炒黄牛肉", "spicy": true, "oil_level": "low", "price": 45}]},{ "store": "辣么火·传统川菜", "distance": "900m", "rating": 4.5, "dishes": [{"name": "水煮鱼", "spicy": true, "oil_level": "high", "price": 68}]}]
5. LLM 结合记忆进行推理和选择
LLM 现在拥有:
用户约束:辣、不油
长期记忆:用户喜欢“少油麻辣香锅”,讨厌“油大”的菜(辣子鸡反馈)
短期记忆:三家候选店铺及菜品油量标注
LLM 的思维链推理(可视为内部提示):
最终选择:
店铺:川西坝子·少油麻辣香锅
菜品:招牌少油香锅(微辣,少油)
数量:1份
价格:38元 + 配送费 5元 = 43元
6. LLM 再次决定调用工具(第二次:执行下单)
规划模块步骤5要求调用 下单工具。LLM 生成调用参数(部分来自记忆):
{"tool": "place_jd_food_order","params": {"store_id": "JD_FOOD_7823","dish": "招牌少油香锅","quantity": 1,"address": "北京市朝阳区XX小区12号楼302","payment": "京东白条","special_requests": "少油,微辣"}}
工具调用京东外卖的真实API,返回订单结果:
{"order_id": "JD202610160001","total_amount": 43.00,"estimated_delivery_time": "19:45","status": "success"}
7. 记忆更新与最终回复
短期记忆:记录本次会话的订单号、金额、预计送达时间。
长期记忆更新:追加一条历史记录 { date: "2026-10-16 19:00", item: "招牌少油香锅", liked: true, from_store: "川西坝子" },增强用户偏好向量。
LLM 生成最终回复:
“已按你‘辣但不油’的要求,在京东外卖上找到附近的‘川西坝子·少油麻辣香锅’店,为你下单了一份招牌少油香锅(微辣、少油),共计43元,使用京东白条支付。预计今晚7:45送达至XX小区12号楼302。订单号JD202610160001。如需更改,请尽快告诉我。”
协同流程对照表(点外卖 vs 机票例子)
步骤 |
机票例子 |
京东点外卖例子 |
|---|---|---|
LLM 接收指令 |
“查明天北京到上海机票,总结表格” |
“晚上想吃辣的不要太油,京东外卖选店下单” |
规划分解 |
①查票 ②获取 ③总结 |
①读记忆 ②定位 ③查外卖 ④评估 ⑤下单 ⑥存记忆 ⑦回复 |
从记忆读取 |
“喜欢早班机” |
默认地址、支付方式、历史喜欢“少油麻辣香锅” |
第一次调工具 |
机票查询API |
京东外卖搜索API(传入位置 辣 低油) |
工具结果存入短期记忆 |
航班列表 |
候选店铺 菜品油量标注 |
LLM 决策 |
选择早班机并制表 |
根据历史偏好和油量选择“川西坝子少油香锅” |
第二次调工具 |
(无,直接总结) |
京东外卖下单API |
最终回复 |
表格形式的航班信息 |
订单确认 送达时间 |
关键差异与启发
多轮工具调用:点外卖需要至少两次工具调用(查询 + 下单),机票例子只需一次查询。
条件分支:点外卖中如果查询结果没有低油辣菜,规划模块会插入“放宽油量限制”或“换关键词”的重试。
长期记忆的动态更新:下单后立即更新偏好,形成个性化循环。
京东App特有约束:工具调用必须遵循京东API的鉴权、地址格式、支付方式等,这需要LLM严格按schema生成参数。
以下提供基于 LangChain 的伪代码实现,演示如何用 LLM + 工具 + 记忆 + 规划 完成“在京东JoyAI上点外卖”任务。
环境准备(伪代码假设)
# 导入 LangChain 相关组件
from langchain.agents import initialize_agent, Tool, AgentType
from langchain.memory import ConversationBufferMemory, VectorStoreRetrieverMemory
from langchain.llms import OpenAI
# 假设使用 OpenAI 模型,可替换为任何 LLM
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain.callbacks import StdOutCallbackHandler
import json
from datetime import datetime
# 模拟京东外卖 API 函数 ------------------------------------------------
def get_user_location():
"""模拟获取用户当前 GPS 位置或默认地址"""
# 实际会调用京东 App 的定位接口
return "北京市朝阳区XX小区12号楼302"
def search_jd_food(location, keywords, radius_km=3):
"""模拟京东外卖搜索接口"""
# 参数示例:location="北京市朝阳区XX小区...", keywords="辣 少油"
mock_results = [
{"store": "川西坝子·少油麻辣香锅",
"distance_km": 0.8,
"rating": 4.8,
"dishes": [{"name": "招牌少油香锅", "spicy": True, "oil_level": "low", "price": 38},
{"name": "微辣牛肉卷", "spicy": True, "oil_level": "medium", "price": 32}]},
{"store": "湘遇·低油菜馆",
"distance_km": 1.2,
"rating": 4.6,
"dishes": [{"name": "少油小炒黄牛肉", "spicy": True, "oil_level": "low", "price": 45}]},
{"store": "辣么火·传统川菜",
"distance_km": 0.9,
"rating": 4.5,
"dishes": [{"name": "水煮鱼", "spicy": True, "oil_level": "high", "price": 68}]}
]
return mock_results
def place_jd_food_order(store_id, dish_name, quantity, address, payment_method, special_requests=""):
"""模拟京东外卖下单接口"""
# 实际会调用京东下单 API,这里返回模拟订单结果
order_id = f"JD{datetime.now().strftime('%Y%m%d%H%M%S')}"
total_amount = 43.00 # 示例金额
estimated_time = "19:45"
return {"order_id": order_id,
"total_amount": total_amount,
"estimated_delivery_time": estimated_time,
"status": "success"}
定义工具(Tools)
将模拟 API 包装成 LangChain 的 Tool 对象,供 LLM 调用。
# 工具1:获取用户位置
def get_location_tool_func(_):
return get_user_location()
location_tool = Tool(
name="GetUserLocation",
func=get_location_tool_func,
description="获取用户当前默认地址。输入可以为空字符串。"
)
# 工具2:搜索京东外卖
def search_food_tool_func(query: str) -> str:
"""query 格式: "location|keywords" 例如 '北京市...|辣 少油'"""
parts = query.split("|")
location = parts[0] if len(parts) > 0 else get_user_location()
keywords = parts[1] if len(parts) > 1 else "辣 不油"
results = search_jd_food(location, keywords)
return json.dumps(results, ensure_ascii=False)
search_tool = Tool(
name="SearchJDFood",
func=search_food_tool_func,
description="搜索京东外卖餐厅和菜品。输入格式: '地址|关键词',例如 '北京市朝阳区XX小区|辣 少油'"
)
# 工具3:下单
def place_order_tool_func(order_json: str) -> str:
"""order_json 包含 store_id, dish_name, quantity, address, payment_method, special_requests"""
data = json.loads(order_json)
result = place_jd_food_order(
store_id=data["store_id"],
dish_name=data["dish_name"],
quantity=data.get("quantity", 1),
address=data["address"],
payment_method=data["payment_method"],
special_requests=data.get("special_requests", "")
)
return json.dumps(result, ensure_ascii=False)
order_tool = Tool(
name="PlaceJDFoodOrder",
func=place_order_tool_func,
description="在京东外卖下单。输入格式为 JSON: {'store_id':..., 'dish_name':..., 'quantity':1, 'address':..., 'payment_method':..., 'special_requests':...}"
)
tools = [location_tool, search_tool, order_tool]
记忆模块(Memory)
我们需要 短期记忆(保存当前会话上下文)和 长期记忆(保存用户偏好)。这里简化演示:使用 ConversationBufferMemory 作为短期记忆,另外用一个简单的字典模拟长期记忆(实际可用向量数据库)。
# 短期记忆:存储最近对话及工具调用结果
short_memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
output_key="output"
)
# 长期记忆:模拟用户偏好(实际可用 Chroma/Pinecone)
long_term_memory = {
"default_address": "北京市朝阳区XX小区12号楼302",
"payment_method": "京东白条",
"food_history": [
{"date": "2025-10-01", "item": "麻辣香锅(少油)", "liked": True},
{"date": "2025-10-05", "item": "辣子鸡", "feedback": "油太大"}
],
"preferred_cuisine": ["川菜", "湘菜"]
}
# 一个简单的检索函数,将长期记忆注入到 prompt 中
def get_long_term_context(user_query: str) -> str:
# 实际根据 query 向量检索,这里直接返回整个偏好
return f"用户长期偏好:默认地址 {long_term_memory['default_address']},支付方式 {long_term_memory['payment_method']}," \
f"历史喜欢的菜:{long_term_memory['food_history'][0]['item']},讨厌油大的食物。"
规划模块(Planning)
LangChain 的 initialize_agent 默认使用 ReAct 风格的 Agent,它本身就具备简单的规划能力(通过 LLM 生成 Thought/Action/Observation 循环)。若需要更复杂的多步规划,可以自定义 AgentExecutor 或使用 PlanAndExecuteAgent。这里我们使用标准 zero-shot-react-description Agent,它的规划隐含在推理步骤中。
为了凸显“规划”,我们写一个显式的规划提示来引导 LLM 按步骤执行,并让 Agent 遵循该规划。
# 自定义规划提示模板
planning_prompt = PromptTemplate(
input_variables=["input", "agent_scratchpad", "chat_history", "long_term_context"],
template="""
你是一个京东外卖助手。你需要按照以下规划步骤执行用户的请求:
【规划步骤】
1. 如果用户没有明确给出地址,先调用 GetUserLocation 工具获取默认地址(从长期记忆获取也可以)。
2. 调用 SearchJDFood 工具,使用地址和“辣 少油”作为关键词,获取附近餐厅列表。
3. 分析搜索结果,结合用户的长期偏好(尤其是讨厌油太大的食物),选择最符合“辣但不油”的餐厅和菜品。
4. 调用 PlaceJDFoodOrder 工具,传入选中的餐厅ID、菜品名、地址、支付方式(从长期记忆获取)等。
5. 返回订单确认信息给用户。
用户长期偏好:{long_term_context}
当前对话历史:{chat_history}
用户最新指令:{input}
{agent_scratchpad}
"""
)
# 初始化 LLM(以 OpenAI 为例,实际可用任何模型)
llm = OpenAI(temperature=0, model_name="gpt-4")
# 创建 Agent
agent = initialize_agent(
tools=tools,
llm=llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
memory=short_memory,
agent_kwargs={"system_message": planning_prompt.template # 注入规划模板
},
verbose=True, # 打印推理过程
handle_parsing_errors=True
)
执行主流程
def run_jd_food_agent(user_input: str):
# 1. 获取长期记忆上下文
long_context = get_long_term_context(user_input)
# 2. 将长期记忆注入到 agent 的额外参数中(简单方式:拼接到输入)
# 实际可以通过 callback 或 memory 的额外字段实现
full_input = f"{user_input}【长期记忆信息】{long_context}"
# 3. 调用 Agent 执行
response = agent.run(full_input)
# 4. 执行后,根据结果更新长期记忆(例如记录本次点的菜)
# 这里简单示例:从 response 中提取订单信息,更新 food_history
if "订单号" in response:
new_record = {"date": datetime.now().strftime("%Y-%m-%d %H:%M"), "item": "招牌少油香锅", "liked": True}
long_term_memory["food_history"].append(new_record)
print("长期记忆已更新")
return response
# 模拟用户输入
user_query = "晚上想吃辣的,不要太油,帮我从京东外卖上选一家附近的店直接下单"
result = run_jd_food_agent(user_query)
print("=== 最终回复 ===", result)
模拟运行输出(Agent 的推理日志)
由于是伪代码,我们模拟一下 Agent 内部产生的 Thought/Action/Observation 序列:
> Entering new AgentExecutor chain...
Thought: 用户要求晚上点辣且不油的外卖。我需要先获得用户地址,然后搜索京东外卖,再选择符合要求的餐厅下单。
Action: GetUserLocation
Action Input: ""
Observation: 北京市朝阳区XX小区12号楼302
Thought: 地址已获得。现在需要搜索京东外卖,关键词为“辣 少油”。
Action: SearchJDFood
Action Input: "北京市朝阳区XX小区12号楼302|辣 少油"
Observation: [{"store": "川西坝子·少油麻辣香锅", "dishes": [{"name": "招牌少油香锅", "oil_level": "low"}...]}, ...]
Thought: 搜索结果中有三家店。根据长期记忆,用户讨厌油大的食物,且历史喜欢麻辣香锅(少油)。川西坝子的招牌少油香锅完全满足“辣且低油”,距离最近,评分最高。因此选择这家店和这个菜品。
Action: PlaceJDFoodOrder
Action Input: {"store_id": "川西坝子·少油麻辣香锅", "dish_name": "招牌少油香锅", "quantity": 1, "address": "北京市朝阳区XX小区12号楼302", "payment_method": "京东白条", "special_requests": "少油,微辣"}
Observation: {"order_id": "JD20261016190001", "total_amount": 43.0, "estimated_delivery_time": "19:45", "status": "success"}
Thought: 下单成功,我已获得订单信息。现在回复用户。
Final Answer: 已按你“辣但不油”的要求,在京东外卖上找到附近的“川西坝子·少油麻辣香锅”店,为你下单了一份招牌少油香锅(微辣、少油),共计43元,使用京东白条支付。预计今晚7:45送达至XX小区12号楼302。订单号JD20261016190001。如需更改,请尽快告诉我。
> Finished chain.
长期记忆已更新
=== 最终回复 ===已按你“辣但不油”的要求...
关键点解释
LLM:OpenAI 模型(或任何兼容模型)作为推理核心。
工具:三个自定义工具分别对应定位、搜索、下单。每个工具都有清晰的描述,Agent 知道何时调用。
记忆:短期 ConversationBufferMemory 记录对话历史,保证多轮交互。长期用简单字典存储用户偏好,并在每次请求时注入到 prompt;执行结束后更新。
规划:通过自定义 prompt 模板,明确写出了规划步骤(1→2→3→4→5),Agent 会按照这个顺序思考,但实际执行时仍依赖于 ReAct 的 Thought/Action 循环,不会机械执行——LLM 会根据观察动态调整(例如如果搜索结果不理想,可能重新搜索)。
这种实现方式已经足够模拟“点外卖”场景下的协同工作。
