1. 项目概述当GPT走进厨房你有没有过这样的经历打开冰箱看着里面零零散散的食材——半根胡萝卜、几个鸡蛋、一块快过期的鸡胸肉还有昨天剩的半碗米饭——脑子里一片空白完全不知道能变出什么花样。或者跟着菜谱做到一半发现家里没有某个关键调料瞬间手足无措。又或者想给家人做顿低卡健康的晚餐却对营养搭配和热量计算一头雾水。这正是我决定动手打造一个“AI厨房助手”的初衷。这个项目我称之为“Recipe Genius”食谱天才它的核心目标很简单让AI成为你厨房里的“副驾驶”。它不是一个简单的菜谱搜索引擎而是一个能理解你现有食材、饮食偏好、甚至烹饪水平的智能伙伴。你告诉它“我有鸡蛋、西红柿和面条想吃点酸甜口的”它就能给你生成一份详细的“番茄鸡蛋打卤面”食谱并附上步骤和注意事项。你问它“这份食谱的热量是多少”它能立刻给你估算出来。为了实现这个目标我选择了两个核心工具GPT-3.5-turbo作为大脑负责理解和生成食谱Agenta作为框架负责快速构建、测试和部署这个AI应用。GPT-3.5-turbo强大的自然语言理解和生成能力让它能处理“冰箱里有什么”这种模糊的输入并输出结构化的菜谱。而Agenta作为一个开源的全栈LLM应用平台极大地简化了Prompt工程、版本管理和部署上线的流程让我能专注于创意和逻辑本身而不是繁琐的工程化问题。这个项目非常适合对AI应用开发感兴趣的开发者、热爱烹饪的极客或者任何想将前沿AI技术落地到具体生活场景的朋友。接下来我将从零开始拆解整个构建过程分享其中的设计思路、技术细节和踩过的坑。2. 核心架构与工具选型解析在动手写第一行代码之前花时间思考架构和选型是至关重要的。一个合理的架构能让你在后续开发中事半功倍而合适的工具则能让你如虎添翼。2.1 为什么选择GPT-3.5-turbo而非GPT-4成本与效能的平衡是首要考量。GPT-3.5-turbo的API调用成本远低于GPT-4这对于一个需要频繁交互、可能面向大量用户的厨房助手应用来说是决定性的优势。在食谱生成这个特定任务上经过我的测试GPT-3.5-turbo的表现已经足够出色。它能很好地理解食材、口味、烹饪方法等指令并生成连贯、合理的文本。当然GPT-4在复杂推理、遵循复杂指令方面更强。但对于“生成一份宫保鸡丁食谱”或“根据现有食材推荐菜式”这类任务GPT-3.5-turbo的能力已经绰绰有余。我们的策略是通过精心设计的Prompt提示词和后续处理逻辑来引导和约束GPT-3.5-turbo的输出弥补其与GPT-4在绝对能力上的差距。这本身就是Prompt工程的价值所在。2.2 AgentaLLM应用开发的“加速器”如果说GPT-3.5-turbo是引擎那么Agenta就是一套优秀的底盘和调试工具。它解决了LLM应用开发中的几个核心痛点Prompt版本管理与对比传统开发中Prompt往往以字符串形式硬编码在代码里修改和对比不同版本非常麻烦。Agenta提供了可视化的界面你可以轻松创建不同版本的Prompt并并行测试它们的输出效果直观地看到哪版Prompt更优。参数化与评估你可以将用户输入如食材列表、系统参数如菜系偏好定义为变量方便地进行A/B测试。Agenta还支持集成评估函数虽然在这个项目中我们更多依赖人工评估但这个功能为未来自动化评估食谱质量提供了可能。快速部署Agenta可以一键将你的应用部署为API端点省去了自己搭建后端服务、处理请求路由和并发的大量工作。这对于快速原型验证和分享成果至关重要。简而言之Agenta让我从“写代码的开发者”部分转变为“调Prompt的产品经理”能更高效地迭代AI应用的核心逻辑。2.3 整体系统架构设计整个“Recipe Genius”的架构可以清晰地分为三层前端交互层一个简单的Web界面。用户在这里输入食材、选择口味如“辣”、“清淡”、设定约束如“30分钟内完成”、“素食”。最初我用了一个极简的HTML页面后期可以扩展为更友好的React或Vue应用。后端逻辑层Agenta 自定义逻辑这是核心。Agenta托管着我们的核心AI智能体Agent。它接收前端传来的结构化数据如JSON然后执行以下流程请求组装将用户输入、系统指令System Prompt和对话历史如有组合成符合OpenAI API格式的messages。调用GPT向OpenAI的GPT-3.5-turbo接口发起请求。后处理对GPT返回的食谱文本进行结构化处理比如提取出菜名、预估烹饪时间、将食材清单和步骤分开。这一步有时需要额外的正则表达式或简单解析逻辑。数据与扩展层Prompt模板库存储在Agenta中是我们最重要的“资产”。可选知识库未来可以考虑接入一个本地的小型食谱数据库用于提供更精准的营养信息热量、蛋白质等或验证AI生成内容的合理性。可选日志与反馈系统记录每次交互收集用户的“点赞”或“踩”用于持续优化Prompt。这个架构清晰、解耦每一层都可以独立演进。例如更换前端界面不会影响后端逻辑未来如果想升级到GPT-4或其他模型也只需在Agenta中修改模型配置即可。3. Prompt工程如何与“食谱天才”有效对话Prompt是与AI模型沟通的“语言”。设计一个好的Prompt就像给一位天才但不太了解人类习惯的厨师写一份清晰的工作说明书。我们的目标是让GPT-3.5-turbo稳定地输出格式统一、内容安全、符合烹饪逻辑的食谱。3.1 系统指令System Prompt设计System Prompt用于设定AI的“角色”和基本行为准则。这是整个Prompt的灵魂。经过多次迭代我最终确定的版本如下你是一位专业、细心且富有创意的中文厨师助手名叫“食谱天才”。你的核心任务是根据用户提供的食材和需求生成详细、可行、安全的中文食谱。 请严格遵守以下规则 1. 输出格式必须严格遵循以下Markdown模板 ## [生成的菜名] **烹饪时间** [预估时间] **难度** [初级/中级/高级] **预估热量每份** [数值] 大卡如信息不足可标注“大致估算” **所需食材** - [食材1][用量]例如鸡胸肉200克 - [食材2][用量] **烹饪步骤** 1. [第一步详细说明] 2. [第二步详细说明] **小贴士** - [贴士1] - [贴士2] 2. 内容要求 - 菜名需贴合食材与需求清晰明了。 - 食材用量需合理、常见如“一汤匙”、“半颗”并优先使用用户提供的食材如需额外常见辅料如油、盐、葱姜蒜可自行添加并注明。 - 烹饪步骤必须详细、顺序正确、且保证操作安全例如明确提醒“热锅冷油”、“小心蒸汽烫伤”。 - 小贴士应提供实用技巧如替代方案、火候关键点、储存建议等。 - 绝对禁止生成涉及任何可能引发安全争议或不符合主流饮食文化的食谱内容。 3. 如果用户提供的食材明显无法构成一道完整的菜或需求矛盾请友好地指出问题并尝试给出调整建议。设计解析角色设定“专业、细心、创意的中文厨师助手”给了AI一个明确的身份这能引导其使用更专业、体贴的语气。结构化输出强制要求Markdown模板是成功的关键。这确保了每次输出的信息结构一致便于前端解析和展示。没有这个约束GPT的输出会非常随意。安全与合理性规则中明确要求“操作安全”和“禁止生成争议内容”这是非常重要的护栏。同时要求优先使用用户食材、用量合理确保了食谱的实用性。容错处理最后一条规则让AI学会处理异常输入提供更友好的用户体验而不是直接报错或胡编乱造。3.2 用户对话User Prompt构建User Prompt是用户的具体请求。我们需要在前端将其结构化再传递给Agenta。例如用户输入被转化为可用食材鸡胸肉200克 broccoli西兰花1颗 大蒜3瓣 生姜一小块。 需求想要一个低脂、做法简单的快手菜口味偏好咸香。在Agenta中我们会将这个结构化的信息与上面的System Prompt组合形成最终的对话上下文发送给GPT-3.5-turbo。3.3 温度Temperature与核采样Top-p参数调优这两个参数控制着GPT输出的“创造性”和“随机性”。Temperature较低值如0.2-0.5使输出更确定、更保守较高值如0.7-1.0使输出更多样、更有创意。Top-p核采样与Temperature配合使用。通常设置为0.9-1。对于食谱生成我经过测试发现Temperature0.3 Top-p0.9是一个甜点。这个设置能保证食谱的基本步骤和用料合理、稳定低随机性同时在菜名和小贴士上保留一定的创意空间避免每次输出都一样。如果设置得太高可能会产生“用冰淇淋炒西兰花”这种离谱的搭配设置得太低则可能让食谱显得呆板。实操心得Prompt工程是一个迭代过程。不要指望一次写对。在Agenta中创建多个Prompt版本用同样的用户输入如“只有鸡蛋和番茄”去测试对比输出结果。你会发现微调几个词比如把“生成食谱”改为“构思一份详细食谱”或者调整格式要求都会对结果产生显著影响。这个过程需要耐心和烹饪常识。4. 使用Agenta构建与部署全流程有了清晰的设计和Prompt我们就可以在Agenta平台上动手实现了。以下是从零开始的关键步骤。4.1 环境准备与Agenta初始化首先确保你的开发环境已经安装了Python建议3.9和pip。# 1. 安装Agenta命令行工具 pip install agenta # 2. 登录Agenta需要先在官网注册账号获取API Key agenta login # 3. 初始化一个新项目 agenta init recipe-genius cd recipe-genius执行agenta init后它会自动创建一个标准化的项目目录结构包含app.py主应用文件、requirements.txt等非常清晰。4.2 编写核心应用逻辑app.py在生成的app.py文件中我们需要定义应用的核心函数。Agenta使用agenta.post装饰器来定义API端点。import agenta from agenta import FloatParam, TextParam import openai import os # 从环境变量读取OpenAI API Key安全起见不要硬编码 openai.api_key os.environ.get(OPENAI_API_KEY) # 定义可调节的参数这些会在Agenta Web界面上显示为滑块或输入框 temperature_param FloatParam(default0.3, minval0.0, maxval1.0) top_p_param FloatParam(default0.9, minval0.0, maxval1.0) system_prompt_param TextParam( default这里粘贴上一章节中你精心设计的System Prompt ) agenta.post( /generate, # 将这些参数暴露给Agenta平台方便后续调优 temperaturetemperature_param, top_ptop_p_param, system_promptsystem_prompt_param, ) def generate_recipe( ingredients: str, requirements: str , temperature: float temperature_param.default, top_p: float top_p_param.default, system_prompt: str system_prompt_param.default, ) - str: 根据食材和需求生成食谱。 Args: ingredients: 用户提供的食材列表用逗号或换行分隔。 requirements: 额外需求如“低脂”、“快手”、“不要辣”。 temperature: GPT生成温度。 top_p: GPT核采样参数。 system_prompt: 系统指令。 Returns: 生成的食谱Markdown文本。 # 构建用户消息 user_content f可用食材{ingredients}。 if requirements: user_content f\n需求{requirements}。 # 构建OpenAI API请求消息 messages [ {role: system, content: system_prompt}, {role: user, content: user_content} ] try: # 调用GPT-3.5-turbo response openai.ChatCompletion.create( modelgpt-3.5-turbo, messagesmessages, temperaturetemperature, top_ptop_p, max_tokens1500, # 限制生成长度避免过长 ) recipe_text response.choices[0].message.content.strip() return recipe_text except Exception as e: # 错误处理返回友好信息 return f抱歉食谱生成失败。错误信息{str(e)}。请检查你的网络连接或稍后再试。代码解析参数化temperature,top_p,system_prompt都被定义为Param这意味着你可以在不修改代码的情况下通过Agenta的Web界面动态调整它们并观察输出变化。这是Agenta的核心优势之一。函数定义agenta.post装饰器将函数暴露为POST API端点。输入参数ingredients和requirements对应前端的用户输入。消息组装按照OpenAI的格式组合system和user消息。API调用使用openai.ChatCompletion.create调用GPT-3.5-turbo。注意设置max_tokens防止生成内容过长。错误处理务必添加try-except块避免因API调用失败导致整个服务崩溃给用户返回友好提示。4.3 在Agenta平台上进行调试与版本管理写完代码后真正的乐趣和挑战在于调试和优化。# 在项目根目录启动本地开发服务器 agenta run执行命令后Agenta会在本地启动服务并提供一个Web UI地址通常是http://localhost:3000。创建应用与变体在Web UI中你可以创建你的“Recipe Genius”应用。然后你可以基于初始的Prompt和参数创建多个“变体”Variant。例如你可以创建一个“Variant A”使用严格的Prompt再创建一个“Variant B”使用更具鼓励性语言的Prompt。并行测试在测试界面你可以同时向A和B两个变体发送相同的输入如“鸡蛋番茄糖醋”。界面会并排显示两个变体生成的食谱让你直观地比较哪个更符合预期。评估与迭代你可以手动标记哪个结果更好。基于反馈你可以不断修改System Prompt或调整参数创建新的变体持续迭代优化。这个过程就像是在做“AI烹饪”的A/B测试。4.4 部署为可访问的API服务当调试满意后一键部署非常简单。# 部署到Agenta云平台免费套餐通常够用 agenta deploy部署成功后Agenta会给你一个唯一的API端点URL比如https://your-app-name.agenta.ai/generate。现在任何能发送HTTP POST请求的应用你的前端网页、手机App、甚至聊天机器人都可以通过这个URL来调用你的食谱生成服务了。请求的JSON格式大致如下{ ingredients: 鸡胸肉西兰花大蒜, requirements: 低脂少油30分钟完成 }注意事项在部署前请务必将OPENAI_API_KEY设置为Agenta平台的应用环境变量而不是写在代码里。在Agenta Web界面的应用设置中可以方便地添加和管理环境变量这是保护密钥安全的最佳实践。5. 前端界面快速搭建与功能增强一个可用的后端API需要前端来交互。这里我提供一个极简但功能完整的HTML/JavaScript前端示例你可以将其保存为index.html并直接在现代浏览器中打开。!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title食谱天才 - 你的AI厨房助手/title style body { font-family: sans-serif; max-width: 800px; margin: 2rem auto; padding: 1rem; line-height: 1.6; } .container { border: 1px solid #ccc; border-radius: 8px; padding: 2rem; } h1 { color: #2c3e50; text-align: center; } .input-group { margin-bottom: 1.5rem; } label { display: block; margin-bottom: 0.5rem; font-weight: bold; } textarea, input { width: 100%; padding: 0.8rem; border: 1px solid #bdc3c7; border-radius: 4px; box-sizing: border-box; } button { background-color: #3498db; color: white; padding: 1rem 2rem; border: none; border-radius: 4px; cursor: pointer; font-size: 1rem; width: 100%; } button:hover { background-color: #2980b9; } button:disabled { background-color: #95a5a6; cursor: not-allowed; } #result { margin-top: 2rem; padding: 1rem; border: 1px dashed #3498db; border-radius: 4px; background-color: #f8f9fa; white-space: pre-wrap; } #loading { display: none; text-align: center; margin-top: 1rem; } .error { color: #e74c3c; border-color: #e74c3c; } /style /head body div classcontainer h1 食谱天才 - AI厨房助手/h1 p描述你手头的食材和需求AI将为你生成专属食谱。/p div classinput-group label foringredients可用食材用逗号或换行分隔*/label textarea idingredients rows3 placeholder例如鸡胸肉200克 鸡蛋2个 西红柿1个 大蒜3瓣.../textarea /div div classinput-group label forrequirements额外需求可选/label input typetext idrequirements placeholder例如低卡、快手菜、不要香菜、偏酸甜口... /div button idgenerateBtn onclickgenerateRecipe()生成食谱/button div idloading⏳ AI正在思考中请稍候.../div div idresult/div /div script // 替换成你部署后得到的Agenta API端点URL const API_URL https://your-recipe-genius-app.agenta.ai/generate; async function generateRecipe() { const ingredients document.getElementById(ingredients).value.trim(); const requirements document.getElementById(requirements).value.trim(); const resultDiv document.getElementById(result); const loadingDiv document.getElementById(loading); const button document.getElementById(generateBtn); if (!ingredients) { resultDiv.innerHTML span classerror请至少输入一些食材。/span; return; } // 禁用按钮显示加载中 button.disabled true; loadingDiv.style.display block; resultDiv.innerHTML ; resultDiv.className ; try { const response await fetch(API_URL, { method: POST, headers: { Content-Type: application/json, }, body: JSON.stringify({ ingredients: ingredients, requirements: requirements }), }); const data await response.text(); // Agenta默认返回text if (response.ok) { // 使用一个简单的Markdown解析器这里仅做示例实际可用marked.js库 resultDiv.innerHTML renderMarkdown(data); } else { throw new Error(请求失败: ${response.status} - ${data}); } } catch (error) { console.error(Error:, error); resultDiv.innerHTML span classerror生成失败${error.message}。请检查网络或稍后重试。/span; resultDiv.className error; } finally { // 恢复按钮隐藏加载 button.disabled false; loadingDiv.style.display none; } } // 一个极简的Markdown转HTML函数处理加粗、标题和列表 function renderMarkdown(text) { let html text; // 处理 ## 标题 html html.replace(/## (.*?)(\n|$)/g, h2$1/h2); // 处理 **加粗** html html.replace(/\*\*(.*?)\*\*/g, strong$1/strong); // 处理 - 列表项 html html.replace(/^- (.*?)(\n|$)/gm, li$1/li); // 将包含li的段落用ul包裹 if (html.includes(li)) { html html.replace(/(li.*\/li)/s, ul$1/ul); } // 处理数字步骤 1. html html.replace(/^(\d)\. (.*?)(\n|$)/gm, listrong步骤$1:/strong $2/li); if (html.includes(步骤)) { // 简单判断实际需更严谨 html html.replace(/(listrong步骤.*\/li)/s, ol$1/ol); } // 保留换行 html html.replace(/\n/g, br); return html; } /script /body /html这个前端界面虽然简单但包含了核心功能输入食材和需求、调用后端API、展示格式化的食谱结果。renderMarkdown函数是一个基础的Markdown解析器能将后端返回的Markdown文本转换为简单的HTML使食谱展示更美观。6. 进阶优化与问题排查实录项目基本跑通后你会发现一些可以优化和可能遇到的问题。以下是我在实际开发中遇到的典型情况及解决方案。6.1 输出格式不稳定与后处理问题尽管在System Prompt中严格规定了Markdown模板但GPT偶尔还是会“放飞自我”比如忘记写“小贴士”部分或者用“第一步”而不是“1.”来标注步骤。解决方案引入后处理逻辑进行格式校验与修正。在后端generate_recipe函数返回前可以添加一段检查代码import re def post_process_recipe(text: str) - str: 对GPT生成的食谱进行后处理确保格式基本统一 # 确保有标题## if not re.search(r^## ., text, re.MULTILINE): # 尝试提取第一行作为标题 lines text.strip().split(\n) if lines: text f## {lines[0]}\n \n.join(lines[1:]) else: text ## 生成食谱\n text # 确保“烹饪时间”、“难度”等关键字段存在简单正则检查 # 这里可以定义更复杂的规则来修复格式 # ... return text # 在调用GPT获得recipe_text后 processed_recipe post_process_recipe(recipe_text) return processed_recipe更稳健的做法是使用**输出解析Output Parsing**库如LangChain的PydanticOutputParser直接要求GPT返回一个结构化的JSON对象而不是自由文本。这能从根本上解决格式问题但需要更复杂的Prompt设计。6.2 生成内容的安全性与合理性检查问题虽然Prompt中已做要求但AI仍有可能生成不常见或存在轻微安全隐患的搭配例如建议生食某些通常应熟食的豆类。解决方案建立关键词过滤与人工审核通道。关键词黑名单在后处理阶段检查生成的食谱文本中是否包含如“生食四季豆”、“未灭菌蜂蜜针对婴儿”等高风险词汇如果包含则触发警告或重新生成。添加免责声明在最终输出给用户的食谱末尾自动追加一段固定声明“本食谱由AI生成仅供参考。请确保食材新鲜并彻底煮熟特别是肉类、禽类、蛋类和豆类。如有特殊饮食要求或健康状况请咨询专业医师或营养师。”用户反馈机制在前端添加“报告问题”按钮将可疑食谱标记便于后期人工复查和优化Prompt。6.3 处理模糊或矛盾的输入问题用户输入“只有水和盐”或者“用巧克力和牛肉做一道甜点”。解决方案在Prompt中我们已经要求AI友好地指出问题。但为了体验更好可以在调用GPT之前在后端添加一层简单的逻辑预检def validate_input(ingredients: str, requirements: str) - tuple[bool, str]: 简单验证输入返回是否有效和提示信息 if not ingredients or len(ingredients.strip()) 2: return False, 请输入至少一种食材。 # 可以扩展更多规则比如检测食材数量过少 ingredient_list [i.strip() for i in ingredients.split(,) if i.strip()] if len(ingredient_list) 2: # 如果只有一种食材可以警告但继续 return True, 提示食材种类较少AI的发挥空间可能有限哦。 return True, 6.4 性能与成本优化问题API调用有延迟且GPT-3.5-turbo按Token收费如何优化解决方案缓存Caching对相同的ingredients和requirements组合将生成的食谱缓存起来可以存在内存数据库如Redis或本地文件。下次相同请求直接返回缓存结果极大减少API调用和延迟。注意设置合理的缓存过期时间。限制输入长度在前端或后端校验用户输入的食材描述长度提示用户不要输入大段无关文本。设置max_tokens如代码中所设限制GPT回复的最大长度避免生成冗长无关内容控制成本。异步处理如果前端需要等待时间较长可以考虑改为异步任务先返回“正在生成”的状态生成完毕后再通知用户。6.5 常见错误排查表问题现象可能原因排查步骤与解决方案前端点击无反应控制台报错1. API_URL填写错误。2. 跨域问题CORS。3. Agenta服务未启动或部署失败。1. 检查API_URL变量值是否正确末尾有无多余空格。2. 如果前端文件用file://打开浏览器会因安全策略阻止请求。请使用本地HTTP服务器如python -m http.server运行前端。3. 运行agenta status检查服务或去Agenta云平台查看应用状态。返回“食谱生成失败”或OpenAI错误1. OpenAI API Key未设置或无效。2. 账户余额不足或达到速率限制。3. 请求参数格式错误。1. 确认OPENAI_API_KEY已正确设置为Agenta应用的环境变量。2. 登录OpenAI平台检查用量和余额。3. 检查后端代码中messages的组装格式是否符合OpenAI API文档要求。生成的食谱格式混乱1. System Prompt中格式指令不够严格。2. Temperature参数设置过高。1. 回到Agenta平台优化System Prompt用更明确的例子和分隔符如---来强调格式。2. 将temperature参数调低至0.2-0.5范围再测试。食谱内容不合理或荒谬1. 用户输入过于模糊或矛盾。2. Prompt未能有效约束AI的“想象力”。1. 在前端增加输入引导和示例。2. 在System Prompt中增加更具体的约束例如“必须使用常见的中式烹饪方法”、“禁止使用非食用材料”。Agenta变体测试无差异1. 不同变体间的Prompt或参数修改未生效。2. 测试输入过于简单不足以体现差异。1. 在Agenta Web UI中确认变体已保存并使用“Evaluate”功能进行对比测试。2. 使用更复杂、边缘的输入进行测试如“只有巧克力和米饭”。构建这个“AI厨房助手”的过程是一次将前沿大模型能力与具体生活场景结合的愉快实践。它让我深刻体会到一个好的AI应用其核心不仅是模型本身更是对用户需求的理解、对交互流程的设计以及持续不断的迭代优化。从最初的简单想法到最终能生成一份像模像样食谱的可部署服务Agenta这样的工具极大地降低了工程化门槛。如果你也对AI应用开发感兴趣不妨从这样一个有趣的小项目开始亲手感受一下“创造”的乐趣。
基于GPT-3.5与Agenta的AI厨房助手:从Prompt工程到部署实践
1. 项目概述当GPT走进厨房你有没有过这样的经历打开冰箱看着里面零零散散的食材——半根胡萝卜、几个鸡蛋、一块快过期的鸡胸肉还有昨天剩的半碗米饭——脑子里一片空白完全不知道能变出什么花样。或者跟着菜谱做到一半发现家里没有某个关键调料瞬间手足无措。又或者想给家人做顿低卡健康的晚餐却对营养搭配和热量计算一头雾水。这正是我决定动手打造一个“AI厨房助手”的初衷。这个项目我称之为“Recipe Genius”食谱天才它的核心目标很简单让AI成为你厨房里的“副驾驶”。它不是一个简单的菜谱搜索引擎而是一个能理解你现有食材、饮食偏好、甚至烹饪水平的智能伙伴。你告诉它“我有鸡蛋、西红柿和面条想吃点酸甜口的”它就能给你生成一份详细的“番茄鸡蛋打卤面”食谱并附上步骤和注意事项。你问它“这份食谱的热量是多少”它能立刻给你估算出来。为了实现这个目标我选择了两个核心工具GPT-3.5-turbo作为大脑负责理解和生成食谱Agenta作为框架负责快速构建、测试和部署这个AI应用。GPT-3.5-turbo强大的自然语言理解和生成能力让它能处理“冰箱里有什么”这种模糊的输入并输出结构化的菜谱。而Agenta作为一个开源的全栈LLM应用平台极大地简化了Prompt工程、版本管理和部署上线的流程让我能专注于创意和逻辑本身而不是繁琐的工程化问题。这个项目非常适合对AI应用开发感兴趣的开发者、热爱烹饪的极客或者任何想将前沿AI技术落地到具体生活场景的朋友。接下来我将从零开始拆解整个构建过程分享其中的设计思路、技术细节和踩过的坑。2. 核心架构与工具选型解析在动手写第一行代码之前花时间思考架构和选型是至关重要的。一个合理的架构能让你在后续开发中事半功倍而合适的工具则能让你如虎添翼。2.1 为什么选择GPT-3.5-turbo而非GPT-4成本与效能的平衡是首要考量。GPT-3.5-turbo的API调用成本远低于GPT-4这对于一个需要频繁交互、可能面向大量用户的厨房助手应用来说是决定性的优势。在食谱生成这个特定任务上经过我的测试GPT-3.5-turbo的表现已经足够出色。它能很好地理解食材、口味、烹饪方法等指令并生成连贯、合理的文本。当然GPT-4在复杂推理、遵循复杂指令方面更强。但对于“生成一份宫保鸡丁食谱”或“根据现有食材推荐菜式”这类任务GPT-3.5-turbo的能力已经绰绰有余。我们的策略是通过精心设计的Prompt提示词和后续处理逻辑来引导和约束GPT-3.5-turbo的输出弥补其与GPT-4在绝对能力上的差距。这本身就是Prompt工程的价值所在。2.2 AgentaLLM应用开发的“加速器”如果说GPT-3.5-turbo是引擎那么Agenta就是一套优秀的底盘和调试工具。它解决了LLM应用开发中的几个核心痛点Prompt版本管理与对比传统开发中Prompt往往以字符串形式硬编码在代码里修改和对比不同版本非常麻烦。Agenta提供了可视化的界面你可以轻松创建不同版本的Prompt并并行测试它们的输出效果直观地看到哪版Prompt更优。参数化与评估你可以将用户输入如食材列表、系统参数如菜系偏好定义为变量方便地进行A/B测试。Agenta还支持集成评估函数虽然在这个项目中我们更多依赖人工评估但这个功能为未来自动化评估食谱质量提供了可能。快速部署Agenta可以一键将你的应用部署为API端点省去了自己搭建后端服务、处理请求路由和并发的大量工作。这对于快速原型验证和分享成果至关重要。简而言之Agenta让我从“写代码的开发者”部分转变为“调Prompt的产品经理”能更高效地迭代AI应用的核心逻辑。2.3 整体系统架构设计整个“Recipe Genius”的架构可以清晰地分为三层前端交互层一个简单的Web界面。用户在这里输入食材、选择口味如“辣”、“清淡”、设定约束如“30分钟内完成”、“素食”。最初我用了一个极简的HTML页面后期可以扩展为更友好的React或Vue应用。后端逻辑层Agenta 自定义逻辑这是核心。Agenta托管着我们的核心AI智能体Agent。它接收前端传来的结构化数据如JSON然后执行以下流程请求组装将用户输入、系统指令System Prompt和对话历史如有组合成符合OpenAI API格式的messages。调用GPT向OpenAI的GPT-3.5-turbo接口发起请求。后处理对GPT返回的食谱文本进行结构化处理比如提取出菜名、预估烹饪时间、将食材清单和步骤分开。这一步有时需要额外的正则表达式或简单解析逻辑。数据与扩展层Prompt模板库存储在Agenta中是我们最重要的“资产”。可选知识库未来可以考虑接入一个本地的小型食谱数据库用于提供更精准的营养信息热量、蛋白质等或验证AI生成内容的合理性。可选日志与反馈系统记录每次交互收集用户的“点赞”或“踩”用于持续优化Prompt。这个架构清晰、解耦每一层都可以独立演进。例如更换前端界面不会影响后端逻辑未来如果想升级到GPT-4或其他模型也只需在Agenta中修改模型配置即可。3. Prompt工程如何与“食谱天才”有效对话Prompt是与AI模型沟通的“语言”。设计一个好的Prompt就像给一位天才但不太了解人类习惯的厨师写一份清晰的工作说明书。我们的目标是让GPT-3.5-turbo稳定地输出格式统一、内容安全、符合烹饪逻辑的食谱。3.1 系统指令System Prompt设计System Prompt用于设定AI的“角色”和基本行为准则。这是整个Prompt的灵魂。经过多次迭代我最终确定的版本如下你是一位专业、细心且富有创意的中文厨师助手名叫“食谱天才”。你的核心任务是根据用户提供的食材和需求生成详细、可行、安全的中文食谱。 请严格遵守以下规则 1. 输出格式必须严格遵循以下Markdown模板 ## [生成的菜名] **烹饪时间** [预估时间] **难度** [初级/中级/高级] **预估热量每份** [数值] 大卡如信息不足可标注“大致估算” **所需食材** - [食材1][用量]例如鸡胸肉200克 - [食材2][用量] **烹饪步骤** 1. [第一步详细说明] 2. [第二步详细说明] **小贴士** - [贴士1] - [贴士2] 2. 内容要求 - 菜名需贴合食材与需求清晰明了。 - 食材用量需合理、常见如“一汤匙”、“半颗”并优先使用用户提供的食材如需额外常见辅料如油、盐、葱姜蒜可自行添加并注明。 - 烹饪步骤必须详细、顺序正确、且保证操作安全例如明确提醒“热锅冷油”、“小心蒸汽烫伤”。 - 小贴士应提供实用技巧如替代方案、火候关键点、储存建议等。 - 绝对禁止生成涉及任何可能引发安全争议或不符合主流饮食文化的食谱内容。 3. 如果用户提供的食材明显无法构成一道完整的菜或需求矛盾请友好地指出问题并尝试给出调整建议。设计解析角色设定“专业、细心、创意的中文厨师助手”给了AI一个明确的身份这能引导其使用更专业、体贴的语气。结构化输出强制要求Markdown模板是成功的关键。这确保了每次输出的信息结构一致便于前端解析和展示。没有这个约束GPT的输出会非常随意。安全与合理性规则中明确要求“操作安全”和“禁止生成争议内容”这是非常重要的护栏。同时要求优先使用用户食材、用量合理确保了食谱的实用性。容错处理最后一条规则让AI学会处理异常输入提供更友好的用户体验而不是直接报错或胡编乱造。3.2 用户对话User Prompt构建User Prompt是用户的具体请求。我们需要在前端将其结构化再传递给Agenta。例如用户输入被转化为可用食材鸡胸肉200克 broccoli西兰花1颗 大蒜3瓣 生姜一小块。 需求想要一个低脂、做法简单的快手菜口味偏好咸香。在Agenta中我们会将这个结构化的信息与上面的System Prompt组合形成最终的对话上下文发送给GPT-3.5-turbo。3.3 温度Temperature与核采样Top-p参数调优这两个参数控制着GPT输出的“创造性”和“随机性”。Temperature较低值如0.2-0.5使输出更确定、更保守较高值如0.7-1.0使输出更多样、更有创意。Top-p核采样与Temperature配合使用。通常设置为0.9-1。对于食谱生成我经过测试发现Temperature0.3 Top-p0.9是一个甜点。这个设置能保证食谱的基本步骤和用料合理、稳定低随机性同时在菜名和小贴士上保留一定的创意空间避免每次输出都一样。如果设置得太高可能会产生“用冰淇淋炒西兰花”这种离谱的搭配设置得太低则可能让食谱显得呆板。实操心得Prompt工程是一个迭代过程。不要指望一次写对。在Agenta中创建多个Prompt版本用同样的用户输入如“只有鸡蛋和番茄”去测试对比输出结果。你会发现微调几个词比如把“生成食谱”改为“构思一份详细食谱”或者调整格式要求都会对结果产生显著影响。这个过程需要耐心和烹饪常识。4. 使用Agenta构建与部署全流程有了清晰的设计和Prompt我们就可以在Agenta平台上动手实现了。以下是从零开始的关键步骤。4.1 环境准备与Agenta初始化首先确保你的开发环境已经安装了Python建议3.9和pip。# 1. 安装Agenta命令行工具 pip install agenta # 2. 登录Agenta需要先在官网注册账号获取API Key agenta login # 3. 初始化一个新项目 agenta init recipe-genius cd recipe-genius执行agenta init后它会自动创建一个标准化的项目目录结构包含app.py主应用文件、requirements.txt等非常清晰。4.2 编写核心应用逻辑app.py在生成的app.py文件中我们需要定义应用的核心函数。Agenta使用agenta.post装饰器来定义API端点。import agenta from agenta import FloatParam, TextParam import openai import os # 从环境变量读取OpenAI API Key安全起见不要硬编码 openai.api_key os.environ.get(OPENAI_API_KEY) # 定义可调节的参数这些会在Agenta Web界面上显示为滑块或输入框 temperature_param FloatParam(default0.3, minval0.0, maxval1.0) top_p_param FloatParam(default0.9, minval0.0, maxval1.0) system_prompt_param TextParam( default这里粘贴上一章节中你精心设计的System Prompt ) agenta.post( /generate, # 将这些参数暴露给Agenta平台方便后续调优 temperaturetemperature_param, top_ptop_p_param, system_promptsystem_prompt_param, ) def generate_recipe( ingredients: str, requirements: str , temperature: float temperature_param.default, top_p: float top_p_param.default, system_prompt: str system_prompt_param.default, ) - str: 根据食材和需求生成食谱。 Args: ingredients: 用户提供的食材列表用逗号或换行分隔。 requirements: 额外需求如“低脂”、“快手”、“不要辣”。 temperature: GPT生成温度。 top_p: GPT核采样参数。 system_prompt: 系统指令。 Returns: 生成的食谱Markdown文本。 # 构建用户消息 user_content f可用食材{ingredients}。 if requirements: user_content f\n需求{requirements}。 # 构建OpenAI API请求消息 messages [ {role: system, content: system_prompt}, {role: user, content: user_content} ] try: # 调用GPT-3.5-turbo response openai.ChatCompletion.create( modelgpt-3.5-turbo, messagesmessages, temperaturetemperature, top_ptop_p, max_tokens1500, # 限制生成长度避免过长 ) recipe_text response.choices[0].message.content.strip() return recipe_text except Exception as e: # 错误处理返回友好信息 return f抱歉食谱生成失败。错误信息{str(e)}。请检查你的网络连接或稍后再试。代码解析参数化temperature,top_p,system_prompt都被定义为Param这意味着你可以在不修改代码的情况下通过Agenta的Web界面动态调整它们并观察输出变化。这是Agenta的核心优势之一。函数定义agenta.post装饰器将函数暴露为POST API端点。输入参数ingredients和requirements对应前端的用户输入。消息组装按照OpenAI的格式组合system和user消息。API调用使用openai.ChatCompletion.create调用GPT-3.5-turbo。注意设置max_tokens防止生成内容过长。错误处理务必添加try-except块避免因API调用失败导致整个服务崩溃给用户返回友好提示。4.3 在Agenta平台上进行调试与版本管理写完代码后真正的乐趣和挑战在于调试和优化。# 在项目根目录启动本地开发服务器 agenta run执行命令后Agenta会在本地启动服务并提供一个Web UI地址通常是http://localhost:3000。创建应用与变体在Web UI中你可以创建你的“Recipe Genius”应用。然后你可以基于初始的Prompt和参数创建多个“变体”Variant。例如你可以创建一个“Variant A”使用严格的Prompt再创建一个“Variant B”使用更具鼓励性语言的Prompt。并行测试在测试界面你可以同时向A和B两个变体发送相同的输入如“鸡蛋番茄糖醋”。界面会并排显示两个变体生成的食谱让你直观地比较哪个更符合预期。评估与迭代你可以手动标记哪个结果更好。基于反馈你可以不断修改System Prompt或调整参数创建新的变体持续迭代优化。这个过程就像是在做“AI烹饪”的A/B测试。4.4 部署为可访问的API服务当调试满意后一键部署非常简单。# 部署到Agenta云平台免费套餐通常够用 agenta deploy部署成功后Agenta会给你一个唯一的API端点URL比如https://your-app-name.agenta.ai/generate。现在任何能发送HTTP POST请求的应用你的前端网页、手机App、甚至聊天机器人都可以通过这个URL来调用你的食谱生成服务了。请求的JSON格式大致如下{ ingredients: 鸡胸肉西兰花大蒜, requirements: 低脂少油30分钟完成 }注意事项在部署前请务必将OPENAI_API_KEY设置为Agenta平台的应用环境变量而不是写在代码里。在Agenta Web界面的应用设置中可以方便地添加和管理环境变量这是保护密钥安全的最佳实践。5. 前端界面快速搭建与功能增强一个可用的后端API需要前端来交互。这里我提供一个极简但功能完整的HTML/JavaScript前端示例你可以将其保存为index.html并直接在现代浏览器中打开。!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title食谱天才 - 你的AI厨房助手/title style body { font-family: sans-serif; max-width: 800px; margin: 2rem auto; padding: 1rem; line-height: 1.6; } .container { border: 1px solid #ccc; border-radius: 8px; padding: 2rem; } h1 { color: #2c3e50; text-align: center; } .input-group { margin-bottom: 1.5rem; } label { display: block; margin-bottom: 0.5rem; font-weight: bold; } textarea, input { width: 100%; padding: 0.8rem; border: 1px solid #bdc3c7; border-radius: 4px; box-sizing: border-box; } button { background-color: #3498db; color: white; padding: 1rem 2rem; border: none; border-radius: 4px; cursor: pointer; font-size: 1rem; width: 100%; } button:hover { background-color: #2980b9; } button:disabled { background-color: #95a5a6; cursor: not-allowed; } #result { margin-top: 2rem; padding: 1rem; border: 1px dashed #3498db; border-radius: 4px; background-color: #f8f9fa; white-space: pre-wrap; } #loading { display: none; text-align: center; margin-top: 1rem; } .error { color: #e74c3c; border-color: #e74c3c; } /style /head body div classcontainer h1 食谱天才 - AI厨房助手/h1 p描述你手头的食材和需求AI将为你生成专属食谱。/p div classinput-group label foringredients可用食材用逗号或换行分隔*/label textarea idingredients rows3 placeholder例如鸡胸肉200克 鸡蛋2个 西红柿1个 大蒜3瓣.../textarea /div div classinput-group label forrequirements额外需求可选/label input typetext idrequirements placeholder例如低卡、快手菜、不要香菜、偏酸甜口... /div button idgenerateBtn onclickgenerateRecipe()生成食谱/button div idloading⏳ AI正在思考中请稍候.../div div idresult/div /div script // 替换成你部署后得到的Agenta API端点URL const API_URL https://your-recipe-genius-app.agenta.ai/generate; async function generateRecipe() { const ingredients document.getElementById(ingredients).value.trim(); const requirements document.getElementById(requirements).value.trim(); const resultDiv document.getElementById(result); const loadingDiv document.getElementById(loading); const button document.getElementById(generateBtn); if (!ingredients) { resultDiv.innerHTML span classerror请至少输入一些食材。/span; return; } // 禁用按钮显示加载中 button.disabled true; loadingDiv.style.display block; resultDiv.innerHTML ; resultDiv.className ; try { const response await fetch(API_URL, { method: POST, headers: { Content-Type: application/json, }, body: JSON.stringify({ ingredients: ingredients, requirements: requirements }), }); const data await response.text(); // Agenta默认返回text if (response.ok) { // 使用一个简单的Markdown解析器这里仅做示例实际可用marked.js库 resultDiv.innerHTML renderMarkdown(data); } else { throw new Error(请求失败: ${response.status} - ${data}); } } catch (error) { console.error(Error:, error); resultDiv.innerHTML span classerror生成失败${error.message}。请检查网络或稍后重试。/span; resultDiv.className error; } finally { // 恢复按钮隐藏加载 button.disabled false; loadingDiv.style.display none; } } // 一个极简的Markdown转HTML函数处理加粗、标题和列表 function renderMarkdown(text) { let html text; // 处理 ## 标题 html html.replace(/## (.*?)(\n|$)/g, h2$1/h2); // 处理 **加粗** html html.replace(/\*\*(.*?)\*\*/g, strong$1/strong); // 处理 - 列表项 html html.replace(/^- (.*?)(\n|$)/gm, li$1/li); // 将包含li的段落用ul包裹 if (html.includes(li)) { html html.replace(/(li.*\/li)/s, ul$1/ul); } // 处理数字步骤 1. html html.replace(/^(\d)\. (.*?)(\n|$)/gm, listrong步骤$1:/strong $2/li); if (html.includes(步骤)) { // 简单判断实际需更严谨 html html.replace(/(listrong步骤.*\/li)/s, ol$1/ol); } // 保留换行 html html.replace(/\n/g, br); return html; } /script /body /html这个前端界面虽然简单但包含了核心功能输入食材和需求、调用后端API、展示格式化的食谱结果。renderMarkdown函数是一个基础的Markdown解析器能将后端返回的Markdown文本转换为简单的HTML使食谱展示更美观。6. 进阶优化与问题排查实录项目基本跑通后你会发现一些可以优化和可能遇到的问题。以下是我在实际开发中遇到的典型情况及解决方案。6.1 输出格式不稳定与后处理问题尽管在System Prompt中严格规定了Markdown模板但GPT偶尔还是会“放飞自我”比如忘记写“小贴士”部分或者用“第一步”而不是“1.”来标注步骤。解决方案引入后处理逻辑进行格式校验与修正。在后端generate_recipe函数返回前可以添加一段检查代码import re def post_process_recipe(text: str) - str: 对GPT生成的食谱进行后处理确保格式基本统一 # 确保有标题## if not re.search(r^## ., text, re.MULTILINE): # 尝试提取第一行作为标题 lines text.strip().split(\n) if lines: text f## {lines[0]}\n \n.join(lines[1:]) else: text ## 生成食谱\n text # 确保“烹饪时间”、“难度”等关键字段存在简单正则检查 # 这里可以定义更复杂的规则来修复格式 # ... return text # 在调用GPT获得recipe_text后 processed_recipe post_process_recipe(recipe_text) return processed_recipe更稳健的做法是使用**输出解析Output Parsing**库如LangChain的PydanticOutputParser直接要求GPT返回一个结构化的JSON对象而不是自由文本。这能从根本上解决格式问题但需要更复杂的Prompt设计。6.2 生成内容的安全性与合理性检查问题虽然Prompt中已做要求但AI仍有可能生成不常见或存在轻微安全隐患的搭配例如建议生食某些通常应熟食的豆类。解决方案建立关键词过滤与人工审核通道。关键词黑名单在后处理阶段检查生成的食谱文本中是否包含如“生食四季豆”、“未灭菌蜂蜜针对婴儿”等高风险词汇如果包含则触发警告或重新生成。添加免责声明在最终输出给用户的食谱末尾自动追加一段固定声明“本食谱由AI生成仅供参考。请确保食材新鲜并彻底煮熟特别是肉类、禽类、蛋类和豆类。如有特殊饮食要求或健康状况请咨询专业医师或营养师。”用户反馈机制在前端添加“报告问题”按钮将可疑食谱标记便于后期人工复查和优化Prompt。6.3 处理模糊或矛盾的输入问题用户输入“只有水和盐”或者“用巧克力和牛肉做一道甜点”。解决方案在Prompt中我们已经要求AI友好地指出问题。但为了体验更好可以在调用GPT之前在后端添加一层简单的逻辑预检def validate_input(ingredients: str, requirements: str) - tuple[bool, str]: 简单验证输入返回是否有效和提示信息 if not ingredients or len(ingredients.strip()) 2: return False, 请输入至少一种食材。 # 可以扩展更多规则比如检测食材数量过少 ingredient_list [i.strip() for i in ingredients.split(,) if i.strip()] if len(ingredient_list) 2: # 如果只有一种食材可以警告但继续 return True, 提示食材种类较少AI的发挥空间可能有限哦。 return True, 6.4 性能与成本优化问题API调用有延迟且GPT-3.5-turbo按Token收费如何优化解决方案缓存Caching对相同的ingredients和requirements组合将生成的食谱缓存起来可以存在内存数据库如Redis或本地文件。下次相同请求直接返回缓存结果极大减少API调用和延迟。注意设置合理的缓存过期时间。限制输入长度在前端或后端校验用户输入的食材描述长度提示用户不要输入大段无关文本。设置max_tokens如代码中所设限制GPT回复的最大长度避免生成冗长无关内容控制成本。异步处理如果前端需要等待时间较长可以考虑改为异步任务先返回“正在生成”的状态生成完毕后再通知用户。6.5 常见错误排查表问题现象可能原因排查步骤与解决方案前端点击无反应控制台报错1. API_URL填写错误。2. 跨域问题CORS。3. Agenta服务未启动或部署失败。1. 检查API_URL变量值是否正确末尾有无多余空格。2. 如果前端文件用file://打开浏览器会因安全策略阻止请求。请使用本地HTTP服务器如python -m http.server运行前端。3. 运行agenta status检查服务或去Agenta云平台查看应用状态。返回“食谱生成失败”或OpenAI错误1. OpenAI API Key未设置或无效。2. 账户余额不足或达到速率限制。3. 请求参数格式错误。1. 确认OPENAI_API_KEY已正确设置为Agenta应用的环境变量。2. 登录OpenAI平台检查用量和余额。3. 检查后端代码中messages的组装格式是否符合OpenAI API文档要求。生成的食谱格式混乱1. System Prompt中格式指令不够严格。2. Temperature参数设置过高。1. 回到Agenta平台优化System Prompt用更明确的例子和分隔符如---来强调格式。2. 将temperature参数调低至0.2-0.5范围再测试。食谱内容不合理或荒谬1. 用户输入过于模糊或矛盾。2. Prompt未能有效约束AI的“想象力”。1. 在前端增加输入引导和示例。2. 在System Prompt中增加更具体的约束例如“必须使用常见的中式烹饪方法”、“禁止使用非食用材料”。Agenta变体测试无差异1. 不同变体间的Prompt或参数修改未生效。2. 测试输入过于简单不足以体现差异。1. 在Agenta Web UI中确认变体已保存并使用“Evaluate”功能进行对比测试。2. 使用更复杂、边缘的输入进行测试如“只有巧克力和米饭”。构建这个“AI厨房助手”的过程是一次将前沿大模型能力与具体生活场景结合的愉快实践。它让我深刻体会到一个好的AI应用其核心不仅是模型本身更是对用户需求的理解、对交互流程的设计以及持续不断的迭代优化。从最初的简单想法到最终能生成一份像模像样食谱的可部署服务Agenta这样的工具极大地降低了工程化门槛。如果你也对AI应用开发感兴趣不妨从这样一个有趣的小项目开始亲手感受一下“创造”的乐趣。