从零搭建你的第一个AI应用
AI 导读
从零搭建你的第一个AI应用 从环境搭建到部署上线,手把手带你完成第一个 AI 聊天应用 Maurice | 灵阙学院 前置准备 Python 3.10+ 一个 OpenAI 或 Anthropic API Key 基本的命令行操作能力 一、搭建 Python 开发环境 创建一个独立的虚拟环境,避免依赖冲突。 # 创建项目目录 mkdir my-first-ai-app && cd...
从零搭建你的第一个AI应用
从环境搭建到部署上线,手把手带你完成第一个 AI 聊天应用 Maurice | 灵阙学院
前置准备
- Python 3.10+
- 一个 OpenAI 或 Anthropic API Key
- 基本的命令行操作能力
一、搭建 Python 开发环境
创建一个独立的虚拟环境,避免依赖冲突。
# 创建项目目录
mkdir my-first-ai-app && cd my-first-ai-app
# 创建虚拟环境
python3 -m venv .venv
# 激活虚拟环境
source .venv/bin/activate # macOS/Linux
# .venv\Scripts\activate # Windows
# 确认 Python 版本
python --version
预期输出:
Python 3.11.x
安装核心依赖:
pip install openai anthropic python-dotenv
创建环境变量文件,存放 API Key(不要提交到 Git):
echo "OPENAI_API_KEY=sk-your-key-here" > .env
echo "ANTHROPIC_API_KEY=sk-ant-your-key-here" >> .env
echo ".env" >> .gitignore
二、第一次调用 AI 模型
创建 chat_basic.py:
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "你是一个友好的中文助手。"},
{"role": "user", "content": "用一句话解释什么是大语言模型。"}
]
)
print(response.choices[0].message.content)
运行:
python chat_basic.py
预期输出:
大语言模型是一种通过海量文本数据训练的深度学习模型,能够理解和生成自然语言。
如果你使用 Anthropic Claude,替换为:
import os
from dotenv import load_dotenv
from anthropic import Anthropic
load_dotenv()
client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
message = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[
{"role": "user", "content": "用一句话解释什么是大语言模型。"}
]
)
print(message.content[0].text)
三、添加流式输出
流式输出让用户看到"逐字生成"的效果,体验更好。创建 chat_stream.py:
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "你是一个友好的中文助手。"},
{"role": "user", "content": "简要介绍 Python 的三大特点。"}
],
stream=True # 关键参数
)
for chunk in stream:
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
print() # 结尾换行
预期输出(逐字显示):
Python 的三大特点:
1. **简洁易读**:语法接近自然语言,学习曲线平缓。
2. **生态丰富**:拥有超过 40 万个第三方包,覆盖几乎所有领域。
3. **跨平台**:同一份代码可在 Windows、macOS、Linux 上运行。
四、添加多轮对话历史
AI 模型本身无状态,需要我们手动维护对话历史。创建 chat_history.py:
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# 对话历史列表
history = [
{"role": "system", "content": "你是一个友好的中文助手,名叫小灵。"}
]
def chat(user_input: str) -> str:
history.append({"role": "user", "content": user_input})
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=history
)
assistant_msg = response.choices[0].message.content
history.append({"role": "assistant", "content": assistant_msg})
return assistant_msg
# 交互式对话循环
print("小灵已上线!输入 'quit' 退出。\n")
while True:
user_input = input("你: ")
if user_input.lower() in ("quit", "exit", "q"):
print("再见!")
break
reply = chat(user_input)
print(f"小灵: {reply}\n")
运行后的交互示例:
小灵已上线!输入 'quit' 退出。
你: 我叫张三
小灵: 你好张三!很高兴认识你,有什么我可以帮你的吗?
你: 你还记得我叫什么吗?
小灵: 当然记得,你叫张三!
你: quit
再见!
五、用 FastAPI 构建 API 服务
安装 FastAPI:
pip install fastapi uvicorn
创建 server.py:
import os
from dotenv import load_dotenv
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from openai import OpenAI
load_dotenv()
app = FastAPI(title="My First AI App")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
class ChatRequest(BaseModel):
messages: list[dict]
stream: bool = False
@app.post("/chat")
async def chat(req: ChatRequest):
if req.stream:
return StreamingResponse(
stream_response(req.messages),
media_type="text/event-stream"
)
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=req.messages
)
return {"content": response.choices[0].message.content}
async def stream_response(messages: list[dict]):
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
stream=True
)
for chunk in stream:
content = chunk.choices[0].delta.content
if content:
yield f"data: {content}\n\n"
yield "data: [DONE]\n\n"
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
启动服务:
python server.py
测试 API:
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-d '{"messages": [{"role": "user", "content": "你好"}]}'
预期输出:
{"content": "你好!有什么我可以帮你的吗?"}
六、添加简单 Web 前端
创建 index.html,放在项目根目录:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>我的第一个 AI 应用</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: system-ui, sans-serif; background: #f5f5f5; }
.container { max-width: 640px; margin: 40px auto; padding: 20px; }
h1 { text-align: center; margin-bottom: 24px; color: #333; }
#chat-box {
background: #fff; border-radius: 12px; padding: 20px;
height: 400px; overflow-y: auto; margin-bottom: 16px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.msg { margin-bottom: 12px; line-height: 1.6; }
.msg.user { text-align: right; }
.msg.user span { background: #007aff; color: #fff; }
.msg.ai span { background: #e9e9eb; color: #333; }
.msg span {
display: inline-block; padding: 8px 14px;
border-radius: 16px; max-width: 80%;
}
.input-row { display: flex; gap: 8px; }
input {
flex: 1; padding: 12px 16px; border-radius: 24px;
border: 1px solid #ddd; font-size: 15px; outline: none;
}
button {
padding: 12px 24px; border-radius: 24px; border: none;
background: #007aff; color: #fff; font-size: 15px; cursor: pointer;
}
button:hover { background: #005ecb; }
</style>
</head>
<body>
<div class="container">
<h1>AI 对话助手</h1>
<div id="chat-box"></div>
<div class="input-row">
<input id="input" placeholder="输入消息..."
onkeydown="if(event.key==='Enter') send()" />
<button onclick="send()">发送</button>
</div>
</div>
<script>
const chatBox = document.getElementById('chat-box');
const input = document.getElementById('input');
const messages = [
{ role: 'system', content: '你是一个友好的中文助手。' }
];
function addMessage(role, text) {
const div = document.createElement('div');
div.className = `msg ${role === 'user' ? 'user' : 'ai'}`;
div.innerHTML = `<span>${text}</span>`;
chatBox.appendChild(div);
chatBox.scrollTop = chatBox.scrollHeight;
}
async function send() {
const text = input.value.trim();
if (!text) return;
input.value = '';
addMessage('user', text);
messages.push({ role: 'user', content: text });
const res = await fetch('http://localhost:8000/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages })
});
const data = await res.json();
addMessage('ai', data.content);
messages.push({ role: 'assistant', content: data.content });
}
</script>
</body>
</html>
让 FastAPI 同时提供静态文件。在 server.py 中加入:
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
# 在 app 定义之后添加
@app.get("/")
async def root():
return FileResponse("index.html")
重启服务后,打开浏览器访问 http://localhost:8000,即可看到聊天界面。
七、项目结构总览
my-first-ai-app/
.env # API Key(不要提交)
.gitignore
.venv/ # 虚拟环境
chat_basic.py # 第一次调用
chat_stream.py # 流式输出
chat_history.py # 多轮对话
server.py # FastAPI 后端
index.html # 前端页面
requirements.txt # pip freeze > requirements.txt
生成依赖文件:
pip freeze > requirements.txt
常见问题
Q1: 报错 openai.AuthenticationError?
检查 .env 中的 API Key 是否正确,确认 load_dotenv() 在 OpenAI() 之前调用。
Q2: 流式输出在浏览器中不生效?
确保 server.py 的 StreamingResponse 使用了 text/event-stream 类型,前端使用 EventSource 或 fetch 的 reader 来读取。
Q3: 对话越来越慢、越来越贵?
对话历史 messages 列表会不断增长。实际项目中需要做截断或摘要压缩,只保留最近 N 轮或用摘要替代早期对话。
Q4: 如何切换到 Claude 模型?
安装 anthropic SDK,使用 Anthropic 客户端替换 OpenAI 客户端,API 参数略有不同(max_tokens 为必填)。
Q5: 如何部署到服务器?
推荐使用 gunicorn + uvicorn worker 部署到 VPS,或者使用 Railway/Render/Fly.io 等 PaaS 平台一键部署。
Maurice | maurice_wen@proton.me