从0到1:构建你的第一个生成式AI应用——智能菜谱生成器

摘要

理论学习的最终目的是为了创造。本文将作为一篇手把手的实战教程,带领您从零开始,一步步构建一个完整、可交互的生成式AI Web应用——“智能菜谱生成器”。我们将使用Python主流的Web框架Flask作为后端,结合OpenAI的API,并将结果呈现给一个简洁美观的前端界面。文章将覆盖从项目环境搭建、后端逻辑编写、API密钥安全管理,到核心Prompt设计、前端页面创建、应用整合部署的全过程。读完本文,您不仅能收获一个有趣的应用,更将掌握将生成式AI能力产品化的核心开发流程。


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

引言:“启智未来”的第一个练手项目

我们的“启智未来”初创团队在深入学习了提示
工程的理论与技巧后,决定启动一个练手项目(Mini-Project)来巩固所学,并将理论付诸实践。他们的想法是,与其直接开发复杂的教育功能,不如先从一个有趣、实用且能体现AI创造力的应用开始。

于是,“智能菜谱生成器”项目应运而生。这个应用的目标很简单:用户输入自己手头拥有的食材,AI就能为他们创造性地生成一份或多份菜谱。这个项目虽小,却“五脏俱全”,完美地涵盖了将一个LLM API封装成用户友好型产品的核心步骤。

让我们跟随“启智未来”的脚步,一起从0到1,完成这次开发之旅。


第一章:应用蓝图:系统架构与技术选型

在敲下第一行代码前,清晰的架构设计是成功的关键。我们的菜谱生成器遵循一个经典的Web应用架构。

数据流转时序图

下图清晰地展示了从用户请求到AI生成菜谱的完整流程:

浏览器 (User) Flask后端 (Python App) OpenAI API 1. 用户提交食材表单 (POST /generate) 2. 构造Prompt并请求API 3. 返回生成的菜谱文本 4. 将菜谱渲染到HTML页面中 浏览器 (User) Flask后端 (Python App) OpenAI API

图1: 智能菜谱生成器数据流转时序图

技术选型

  • 后端: Python 3.x + Flask。Flask是一个轻量级的Python Web框架,非常适合快速开发和原型验证。
  • AI核心: OpenAI API。我们将使用openai官方Python库来与其交互。
  • 前端: HTML + CSS。我们不需要复杂的前端框架,只需基础的HTML表单和CSS样式。

第二章:项目搭建与后端初始化

1. 项目结构

首先,创建一个清晰的项目目录结构:

/recipe-generator
|-- /templates
|   |-- index.html  <-- 前端页面
|-- app.py          <-- Flask应用主文件
|-- requirements.txt  <-- Python依赖
|-- .env            <-- (可选但推荐) 存储环境变量

2. 安装依赖

requirements.txt 文件中写入我们的项目依赖:

flask
openai
python-dotenv
  • flask: Web框架。
  • openai: OpenAI官方库。
  • python-dotenv: (推荐) 用于从.env文件加载环境变量,确保API密钥安全。

然后,在项目根目录下通过以下命令安装它们:

# 创建并激活一个虚拟环境(推荐)
python -m venv venv
source venv/bin/activate # 在Windows上使用 `venv\Scripts\activate`

# 安装依赖
pip install -r requirements.txt

3. API密钥的安全管理

切勿将您的API密钥硬编码在代码中! 这是最重要的安全实践。

在项目根目录创建一个名为 .env 的文件,并在其中存入您的密钥:

OPENAI_API_KEY="sk-YourSecretKeyHere"

同时,将.env文件加入到你的.gitignore中,防止其被提交到代码仓库。

4. 初始化Flask应用

现在,我们来编写 app.py 的初始框架。

# app.py

import os
from flask import Flask, render_template, request
from openai import OpenAI
from dotenv import load_dotenv

# 加载.env文件中的环境变量
load_dotenv()

# 初始化Flask应用
app = Flask(__name__)

# 初始化OpenAI客户端
# 该客户端会自动从环境变量 `OPENAI_API_KEY` 读取密钥
try:
    client = OpenAI()
except Exception as e:
    print(f"Error initializing OpenAI client: {e}")
    # 在实际应用中,这里应该有更健壮的错误处理
    client = None

# 主页路由,显示输入表单
@app.route('/')
def index():
    return render_template('index.html')

# “神奇”发生的地方,处理表单提交和AI交互
@app.route('/generate', methods=['POST'])
def generate_recipe():
    # (这部分逻辑我们将在下一章填充)
    return "菜谱正在生成中..."


# 运行Flask应用
if __name__ == '__main__':
    app.run(debug=True)

第三章:核心逻辑:精心设计菜谱生成Prompt

这是我们应用的大脑。一个好的Prompt,是生成高质量菜谱的关键。

我们将应用之前学到的提示工程技巧:

  • 赋予角色 (Persona): 让AI成为一位“富有创造力的美食家”。
  • 明确指令: 清晰地告诉它要做什么。
  • 结构化输入: 将用户的输入(食材、菜系等)清晰地嵌入提示。
  • 要求输出格式: 要求AI以Markdown格式返回,便于前端展示。

app.py 中,我们来完成 /generate 路由的逻辑:

# ... (app.py 上半部分代码) ...

@app.route('/generate', methods=['POST'])
def generate_recipe():
    if not client:
        return "OpenAI client not initialized. Please check your API key."

    # 从表单获取用户输入
    ingredients = request.form.get('ingredients')
    cuisine = request.form.get('cuisine', '中式') # 默认为中式

    if not ingredients:
        return "请输入您拥有的食材!"

    # --- 精心设计的Prompt ---
    prompt = f"""
    你是一位富有创造力、经验丰富的美食家和菜谱开发者。
    请根据以下信息,为我创作一份详细的菜谱。

    ### 要求 ###
    1.  **主要食材**: {ingredients}
    2.  **期望菜系**: {cuisine}
    3.  **输出格式**: 请使用Markdown格式,包含以下部分:
        -   **菜名**: 给这道菜起一个吸引人的名字。
        -   **简介**: 简单描述这道菜的特色和风味。
        -   **所需食材**: 列出所有需要的食材和用量。
        -   **详细步骤**: 提供清晰、易于遵循的烹饪步骤。
        -   **小贴士**: (可选)提供一两个烹饪小建议。

    请开始你的创作吧!
    """

    try:
        # 调用OpenAI API
        response = client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[
                {"role": "system", "content": "你是一位富有创造力的美食家。"},
                {"role": "user", "content": prompt}
            ],
            temperature=0.8, # 增加一点创造力
            max_tokens=1000
        )
        
        recipe_content = response.choices[0].message.content
        
        # 将生成的内容传递给前端模板
        return render_template('index.html', recipe=recipe_content, ingredients=ingredients, cuisine=cuisine)

    except Exception as e:
        print(f"Error calling OpenAI API: {e}")
        error_message = f"调用AI服务时出错: {e}"
        return render_template('index.html', error=error_message, ingredients=ingredients, cuisine=cuisine)


# ... (app.py 下半部分代码) ...

第四章:创建用户友好的前端界面

现在,我们来创建 templates/index.html 文件。我们将使用一个简单的HTML表单和一些内联CSS来保持项目的简洁性。

<!-- templates/index.html -->

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>智能菜谱生成器</title>
    <style>
        body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; line-height: 1.6; color: #333; max-width: 800px; margin: 40px auto; padding: 20px; background-color: #f9f9f9; }
        .container { background-color: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); }
        h1 { text-align: center; color: #e84393; }
        form { display: flex; flex-direction: column; gap: 15px; }
        input, select, button { font-size: 16px; padding: 10px; border-radius: 5px; border: 1px solid #ddd; }
        button { background-color: #e84393; color: white; border: none; cursor: pointer; transition: background-color 0.3s; }
        button:hover { background-color: #d83383; }
        .recipe-card { margin-top: 30px; padding: 20px; border: 1px solid #eee; border-radius: 8px; background-color: #fff8fb; }
        .error { color: #d63031; }
        /* 简单的Markdown样式 */
        .recipe-card h2 { border-bottom: 2px solid #e84393; padding-bottom: 5px; }
        .recipe-card h3 { color: #6c5ce7; }
        .recipe-card ul, .recipe-card ol { padding-left: 20px; }
        .recipe-card code { background-color: #eee; padding: 2px 4px; border-radius: 3px; }
    </style>
</head>
<body>
    <div class="container">
        <h1>🍳 智能菜谱生成器 📝</h1>
        <form action="/generate" method="post">
            <label for="ingredients">告诉我你有什么食材(用逗号分隔):</label>
            <input type="text" id="ingredients" name="ingredients" value="{{ ingredients or '' }}" placeholder="例如:鸡胸肉, 土豆, 胡萝卜" required>

            <label for="cuisine">你偏爱什么菜系?</label>
            <select id="cuisine" name="cuisine">
                <option value="中式" {% if cuisine == '中式' %}selected{% endif %}>中式</option>
                <option value="西式" {% if cuisine == '西式' %}selected{% endif %}>西式</option>
                <option value="日式" {% if cuisine == '日式' %}selected{% endif %}>日式</option>
                <option value="创意融合" {% if cuisine == '创意融合' %}selected{% endif %}>创意融合</option>
            </select>
            <button type="submit">✨ 生成神奇菜谱 ✨</button>
        </form>

        {% if error %}
            <div class="recipe-card error">
                <p><strong>出错了:</strong> {{ error }}</p>
            </div>
        {% endif %}

        {% if recipe %}
            <div class="recipe-card">
                <!-- 我们需要一个方式将Markdown转换为HTML,但为了简单,我们先用pre标签展示 -->
                <h2>为您生成的菜谱:</h2>
                <pre style="white-space: pre-wrap; font-family: inherit;">{{ recipe }}</pre>
            </div>
        {% endif %}
    </div>
</body>
</html>

注意: 为了让Markdown格式正确显示,最简单的方式是使用<pre>标签。在生产应用中,您可能会使用一个Python库(如markdown2)在后端将Markdown转换为HTML,或者在前端使用JavaScript库(如marked.js)来渲染。


第五章:整合运行你的第一个AI应用

现在,所有部件都已就绪!确保你的 app.pytemplates/index.html 文件内容完整。

运行应用:
在你的项目根目录下,打开终端(确保虚拟环境已激活),然后运行:

flask run

Flask会启动一个本地开发服务器。打开浏览器,访问 http://127.0.0.1:5000,你将看到你的“智能菜谱生成器”!

输入你冰箱里的食材,选择一个菜系,然后点击按钮,见证AI为你创造美食的魔力吧!


总结:超越菜谱,你的GenAI构建之旅

恭喜你!你已经成功构建并运行了自己的第一个生成式AI应用。通过这个项目,你掌握了:

  • Web应用基本架构: 如何组织一个包含前后端的项目。
  • 后端与AI集成: 如何在Flask中安全地调用OpenAI API。
  • 核心Prompt设计: 如何将业务逻辑转化为高效的AI指令。
  • 前后端数据交互: 如何通过表单接收用户输入,并将结果展示在页面上。

这个“智能菜谱生成器”只是一个起点。现在,你可以尝试扩展它:

  • 增加图片生成: 调用DALL-E 3 API,为生成的菜谱配上一张诱人的图片。
  • 保存历史记录: 添加数据库功能,让用户可以保存、收藏他们喜欢的菜谱。
  • 尝试不同模型: 替换为gpt-4或其他模型,看看输出有何不同。

你已经开启了作为一名生成式AI应用构建者的旅程。继续探索,继续创造吧!

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CarlowZJ

我的文章对你有用的话,可以支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值