完整教程:基于多个大模型自己建造一个AI智能助手
基于多个大模型自己建造一个AI智能助手
一、概述
前面在博文 “如何自己建造一个AI智能助手” https://blog.csdn.net/cnds123/article/details/155134935 是基于通义千问(Qwen)API(免费额度可用)构建的AI智能助手。
你只需要一个通义千问的DashScope API Key https://dashscope.console.aliyun.com/apiKey (获取 API Key。阿里云账号免费注册,新用户送额度)。需要用支付宝对账号账号进行实名认证。
下面介绍,基于多个大模型,建造一个AI智能助手。
基于多个大模型自己建造一个AI智能助手,需要获取多个大模型的API Key。这里基于DashScope API Key 和DeepSeek 的API为例演示。
获取 DeepSeek API Key: https://platform.deepseek.com/sign_in
注意:DeepSeek调用 API 服务需要充值。实名认证后再充值,支付金额最少10元。【充值金额仅用于调用 API 服务,网页版及 App 对话免费使用,无需充值。】
需要有一个邮箱验证登录。创建成功后,系统会生成一个以 sk- 开头的 API Key
立即复制并妥善保存这个 Key,因为关闭对话框后通常无法再次查看完整 Key。
编程能力,这里,具体采用:
- 前端:纯 HTML + JavaScript
- 后端:Python FastAPI
- AI 模型:调用DashScope API Key 和DeepSeek 的API
输入框改进行:用多行文本域(<textarea>),不仅能输入多行内容,还能保留换行、缩进等格式,特别适合粘贴 Python 代码、JSON、Markdown 等结构化文本。支持 Enter 发送(避免换行冲突,需按 Ctrl+Enter发送)
注意:在运行这个应用时,需要安装这些第三方库。
安装命令:
pip install fastapi uvicorn httpx pydantic dashscope
解释一下这些第三方库的作用:
FastAPI: 构建API的主要框架。其中,FastAPI创建 Web API 应用的主要类;HTTPException用于抛出 HTTP 错误异常;CORSMiddleware:处理跨域资源共享(CORS)的中间件。
pydantic: 通过Python类型注解来进行数据验证和设置管理。其中BaseModel 用于定义数据模型。
httpx: 支持异步的HTTP客户端。用于向 DeepSeek API 发送请求。
uvicorn: 用于运行FastAPI应用的ASGI服务器。运行 FastAPI 应用。
Dashscope:是阿里云推出的 模型即服务(MaaS)平台,提供包括通义千问(Qwen)在内的多种大模型 API,支持文本生成、图像生成、语音识别等。
先看运行效果截图:

二、源码
项目结构
D:/ai-assistant- multiple/
├── backend/
│ └── main.py
└── frontend/
└── index.html
后端:backend/main.py 文件源码:
# backend/main.py
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import httpx
import json
from enum import Enum
from typing import Optional
import os #
# 模型配置
class ModelType(str, Enum):
DEEPSEEK = "deepseek"
TONGYI = "tongyi"
OPENAI = "openai"
# API 配置
API_CONFIG = {
ModelType.DEEPSEEK: {
"url": "https://api.deepseek.com/v1/chat/completions",
#"api_key": "你的 DeepSeek API Key", # 你的 DeepSeek API Key,从环境变量读取更安全
"api_key": os.getenv("DEEPSEEK_API_KEY"), # ← 这行
"model_name": "deepseek-chat"
},
ModelType.TONGYI: {
"url": "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation",
#"api_key": "你的 Tongyi API Key", # 你的 Tongyi API Key,从环境变量读取更安全
"api_key": os.getenv("DASHSCOPE_API_KEY"), # ← 这行
"model_name": "qwen-plus"
}
}
app = FastAPI()
# 允许前端跨域访问
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class ChatRequest(BaseModel):
message: str
model: ModelType = ModelType.DEEPSEEK # 默认模型
class ModelInfo(BaseModel):
name: str
display_name: str
provider: str
@app.get("/models")
async def get_available_models():
"""获取可用的模型列表"""
models = [
ModelInfo(
name=ModelType.DEEPSEEK,
display_name="DeepSeek Chat",
provider="DeepSeek"
),
ModelInfo(
name=ModelType.TONGYI,
display_name="通义千问",
provider="阿里云"
)
]
return {"models": models}
@app.post("/chat")
async def chat(request: ChatRequest):
try:
config = API_CONFIG.get(request.model)
if not config:
raise HTTPException(status_code=400, detail="不支持的模型")
if request.model == ModelType.TONGYI:
return await call_tongyi_api(request.message, config)
else:
return await call_openai_compatible_api(request.message, config, request.model)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
async def call_openai_compatible_api(message: str, config: dict, model_type: ModelType):
"""调用 OpenAI 兼容的 API(DeepSeek、OpenAI)"""
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {config['api_key']}"
}
payload = {
"model": config["model_name"],
"messages": [
{
"role": "user",
"content": message
}
],
"stream": False
}
async with httpx.AsyncClient() as client:
response = await client.post(
config["url"],
headers=headers,
json=payload,
timeout=30.0
)
if response.status_code == 200:
data = response.json()
return {"reply": data["choices"][0]["message"]["content"]}
else:
error_detail = f"{model_type.value} API 错误: {response.status_code} - {response.text}"
raise HTTPException(status_code=500, detail=error_detail)
async def call_tongyi_api(message: str, config: dict):
"""调用通义千问 API"""
import dashscope
from dashscope import Generation
dashscope.api_key = config["api_key"]
response = Generation.call(
model=config["model_name"],
prompt=message
)
if response.status_code == 200:
return {"reply": response.output.text}
else:
raise HTTPException(status_code=500, detail=f"通义千问 API 错误: {response.status_code}")
@app.get("/")
async def root():
return {"message": "多模型 AI 助手后端服务运行中"}
前端:frontend/index.html文件源码:
多模型 AI 助手 多模型 AI 助手
提示:按 Ctrl+Enter(Windows/Linux)或 Cmd+Enter(Mac)快速发送<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.5/purify.min.js"></script> <script> marked.setOptions({ highlight: function(code, lang) { const language = hljs.getLanguage(lang) ? lang : 'plaintext'; return hljs.highlight(code, { language }).value; }, langPrefix: 'hljs language-' }); const chatBox = document.getElementById('chat-box'); const modelSelect = document.getElementById('model-select'); const input = document.getElementById('user-input'); const sendBtn = document.getElementById('send-btn'); // 自动调整 textarea 高度 input.addEventListener('input', function() { this.style.height = 'auto'; this.style.height = Math.min(this.scrollHeight, 200) + 'px'; }); async function sendMessage() { const msg = input.value.trim(); if (!msg) return; const model = modelSelect.value; // 显示用户消息(保留原始格式) const userDiv = document.createElement('div'); userDiv.className = 'message user'; // 使用保留换行和空格,但用 DOMPurify 防 XSS userDiv.innerHTML = `你:${DOMPurify.sanitize(msg)}`; chatBox.appendChild(userDiv); chatBox.scrollTop = chatBox.scrollHeight; input.value = ''; input.style.height = 'auto'; // 重置高度 sendBtn.disabled = true; sendBtn.textContent = '发送中...'; // 显示“思考中” const thinkingDiv = document.createElement('div'); thinkingDiv.className = 'message ai'; thinkingDiv.innerHTML = 'AI: 正在思考…'; chatBox.appendChild(thinkingDiv); chatBox.scrollTop = chatBox.scrollHeight; try { const res = await fetch('http://localhost:8000/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: msg, model: model }) }); const data = await res.json(); if (res.ok) { const cleanHtml = DOMPurify.sanitize(marked.parse(data.reply)); thinkingDiv.innerHTML = `AI: ${cleanHtml}`; } else { thinkingDiv.innerHTML = `AI: ❌ 出错了:${data.detail || '未知错误'}`; } } catch (err) { thinkingDiv.innerHTML = `AI: ⚠️ 无法连接到后端,请确保它正在运行。`; } finally { sendBtn.disabled = false; sendBtn.textContent = '发送'; } } sendBtn.addEventListener('click', sendMessage); // 支持快捷键发送:Ctrl+Enter / Cmd+Enter input.addEventListener('keydown', (e) => { if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { e.preventDefault(); sendMessage(); } }); </script>提示,可以把 marked.min.js、highlight.min.js、purify.min.js 下载到本地 static/ 目录,改用相对路径。
其中,CDN (Content Delivery Network,内容分发网络)加载 marked 和 highlight.js 用于前端的交互输出格式。让 AI 返回的 代码块、Markdown 格式 能正确显示,并支持 Python 等语言的语法高亮!若缺乏格式输出python代码时就不好用了。
引入purify.min.js,增强安全:purify.min.js 是 DOMPurify 库的压缩版,它的核心作用是: 安全地清理(Sanitize)HTML 字符串,防止 XSS(跨站脚本攻击)。
三、运行步骤
1.启动后端服务
在cmd中(下行若在Windows PowerShell中运行,去掉 /d):
cd /d D:/ai-assistant-multiple/backend
$env:DASHSCOPE_API_KEY="真实的DASHSCOPE_API_KEY "
$env:DEEPSEEK_API_KEY="真实的DEEPSEEK_API_KEY"
uvicorn main:app --port 8000
如果你嫌输入比较麻烦,可以使用批处理文件(.bat)
在D:\ai-assistant-multiple\backend目录中用记事本建立名称为start_backend.bat批处理文件,以后只需双击这个 .bat 文件就能运行后端,无需手动输入命令。内容如下:
@echo off cd /d "D:\ai-assistant-multiple\backend" :: Set API Key set DASHSCOPE_API_KEY=真实的DASHSCOPE_API_KEY set DEEPSEEK_API_KEY=真实的DEEPSEEK_API_KEY echo Starting AI assistant backend... echo Visit http://localhost:8000 to check status echo Open frontend/index.html in your browser echo. uvicorn main:app --port 8000 pause注意,在使用时不要关闭后端服务。
2.打开前端
直接双击 frontend/index.html 用浏览器打开
3.聊天
现在可以在前端网页中开始聊天!
可以在同一个界面中体验不同 AI 模型的回答风格和能力了!
输入框改用多行文本域(<textarea>),不仅能输入多行内容,还能保留换行、缩进等格式,特别适合粘贴 Python 代码、JSON、Markdown 等结构化文本。支持 Enter 发送(避免换行冲突,需按 Ctrl+Enter发送)
用户点击“发送” → 立刻看到“正在思考…”,让用户在等待期间知道系统在工作,不会误以为卡死。
未来可以继续扩展高级功能,如:
· 保存聊天历史
· 部署到公网,7x24 小时可用,分享链接给任何人
浙公网安备 33010602011771号