对话API知识点
获取API Key
API Key可以在DeepSeek官网获取。
获取后建议不要写在代码里面,建议使用环境变量保存
首次调用API
DeepSeek API 使用与 OpenAI 兼容的 API 格式,通过修改配置,您可以使用 OpenAI SDK 来访问 DeepSeek API,或使用与 OpenAI API 兼容的软件。
| PARAM | VALUE |
|---|---|
| base_url * | https://api.deepseek.com |
| api_key | apply for an API key |
-
出于与 OpenAI 兼容考虑,您也可以将
base_url设置为https://api.deepseek.com/v1来使用,但注意,此处v1与模型版本无关。 -
deepseek-chat模型已全面升级为 DeepSeek-V3,接口不变。 通过指定model='deepseek-chat'即可调用 DeepSeek-V3。 -
deepseek-reasoner是 DeepSeek 最新推出的推理模型 DeepSeek-R1。通过指定model='deepseek-reasoner',即可调用 DeepSeek-R1。
调用API示例
curl
curl https://api.deepseek.com/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <DeepSeek API Key>" \
-d '{
"model": "deepseek-chat",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
],
"stream": false
}'
python
# Please install OpenAI SDK first: `pip3 install openai`
# 需要先安装openai支持: `pip3 install openai`
from openai import OpenAI
client = OpenAI(api_key="<DeepSeek API Key>", base_url="https://api.deepseek.com")
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "Hello"},
],
stream=False
)
print(response.choices[0].message.content)
nodejs
// Please install OpenAI SDK first: `npm install openai`
// 需要先安装openai支持: `npm install openai`
import OpenAI from 'openai'
const openai = new OpenAI({
baseURL: 'https://api.deepseek.com',
apiKey: '<DeepSeek API Key>',
})
async function main() {
const completion = await openai.chat.completions.create({
messages: [{role: 'system', content: 'You are a helpful assistant.'}],
model: 'deepseek-chat',
})
console.log(completion.choices[0].message.content)
}
main()
关于role参数
在AI对话系统中,role参数用于区分对话中不同参与者的身份或角色:
messages.push({role: 'user', content: userMessage})
这里的role可以有以下几种取值,每种都有特定含义:
1. 主要角色类型
| 角色(role) | 说明 |
|---|---|
"system" | 系统指令,用于设置AI的初始行为或背景 |
"user" | 用户发送的消息/问题 |
"assistant" | AI助手的回复 |
2. 具体解释
-
system (系统角色)
- 通常放在对话历史的最开始
- 用于设定AI的行为模式或对话上下文
- 例如:
{ role: "system", content: "你是一个专业的医疗助手,用简单易懂的语言回答" }
-
user (用户角色)
- 代表人类用户输入的内容
- 例如:
{ role: "user", content: "感冒有哪些症状?" }
-
assistant (助手角色)
- 代表AI之前的回复内容
- 用于维持对话上下文
- 例如:
{ role: "assistant", content: "感冒常见症状包括..." }
3. 为什么需要区分角色?
- 上下文维护:AI需要知道哪些是用户说的,哪些是自己说过的
- 行为控制:系统消息可以指导AI如何回应
- 多轮对话:保持对话的自然流畅性
4. 实际对话示例
一个完整的messages数组可能长这样:
;[
{role: 'system', content: '你是一个有帮助的助手'},
{role: 'user', content: '你好'},
{role: 'assistant', content: '你好!有什么可以帮您的吗?'},
{role: 'user', content: '推荐几本好书'},
]
5. 在你的代码中的作用
当你执行:
messages.push({role: 'user', content: userMessage})
你是在告诉AI: “接下来这条消息是用户(user)发送的,内容是userMessage”
这样当AI处理时,就能正确理解对话的流向和上下文关系。
6. 高级用法
有些API可能还支持其他角色,如:
"function"- 用于函数调用"tool"- 用于工具调用
但在基础对话场景中,主要使用上述三种基本角色。
本地AI对接DeepSeek
首先需要在DeepSeek官网购买API,获取API Key,随后可以使用脚本搭建一个本地对话
from openai import OpenAI
import os
# 初始化对话历史
messages = [
{"role": "system", "content": "你是一个乐于助人的AI助手"},
]
def main():
# 建议从环境变量读取API Key
api_key = os.getenv("DEEPSEEK_API_KEY") or input("请输入DeepSeek API Key: ")
if not api_key:
print("API Key不能为空!")
return
client = OpenAI(api_key=api_key, base_url="https://api.deepseek.com")
print("请输入任意问题回车发出对话(键入exit退出): ")
counter = 0
while True:
try:
counter += 1
user_input = input(f"{counter}.问:")
if user_input.lower() == "exit":
break
messages.append({"role": "user", "content": user_input})
print(f"{counter}.AI:", end="", flush=True)
assistant_output = ""
response = client.chat.completions.create(
model="deepseek-reasoner",
messages=messages,
stream=True,
)
for chunk in response:
if chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
assistant_output += content
print(content, end="", flush=True)
print("") # 换行
messages.append({"role": "assistant", "content": assistant_output})
except KeyboardInterrupt:
print("\n对话已中断")
break
except Exception as e:
print(f"\n发生错误: {str(e)}")
break
if __name__ == '__main__':
main()
如果需要UI界面,也可以本地创建一个web服务,加入web服务后完整代码如下
from flask import Flask, render_template_string, request, jsonify
from openai import OpenAI
import os
app = Flask(__name__)
# 初始化对话历史
messages = [
{"role": "system", "content": "你是一个乐于助人的AI助手"},
]
# 建议从环境变量读取API Key
api_key = os.getenv("DEEPSEEK_API_KEY")
client = OpenAI(api_key=api_key, base_url="https://api.deepseek.com")
# HTML模板
HTML_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
<title>AI对话助手</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.chat-container {
background-color: white;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 20px;
height: 500px;
overflow-y: auto;
margin-bottom: 20px;
}
.message {
margin-bottom: 15px;
padding: 10px 15px;
border-radius: 18px;
max-width: 70%;
word-wrap: break-word;
}
.user-message {
background-color: #e3f2fd;
margin-left: auto;
border-bottom-right-radius: 5px;
}
.assistant-message {
background-color: #f1f1f1;
margin-right: auto;
border-bottom-left-radius: 5px;
}
#input-form {
display: flex;
gap: 10px;
}
#user-input {
flex-grow: 1;
padding: 10px;
border-radius: 20px;
border: 1px solid #ddd;
}
button {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 20px;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
.typing-indicator {
display: inline-block;
padding: 10px 15px;
background-color: #f1f1f1;
border-radius: 18px;
margin-bottom: 15px;
border-bottom-left-radius: 5px;
}
.typing-dot {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #888;
margin: 0 2px;
animation: typing-animation 1.4s infinite ease-in-out;
}
.typing-dot:nth-child(1) { animation-delay: 0s; }
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes typing-animation {
0%, 60%, 100% { transform: translateY(0); }
30% { transform: translateY(-5px); }
}
</style>
</head>
<body>
<h1>AI对话助手</h1>
<div class="chat-container" id="chat-container">
{% for message in messages %}
{% if message.role == 'user' %}
<div class="message user-message">{{ message.content }}</div>
{% elif message.role == 'assistant' %}
<div class="message assistant-message">{{ message.content }}</div>
{% endif %}
{% endfor %}
<div id="typing-indicator" style="display: none;">
<div class="typing-indicator">
<span class="typing-dot"></span>
<span class="typing-dot"></span>
<span class="typing-dot"></span>
</div>
</div>
</div>
<form id="input-form" onsubmit="sendMessage(); return false;">
<input type="text" id="user-input" placeholder="输入你的问题..." autocomplete="off">
<button type="submit">发送</button>
</form>
<script>
function sendMessage() {
const input = document.getElementById('user-input');
const message = input.value.trim();
if (!message) return;
// 显示用户消息
const chatContainer = document.getElementById('chat-container');
const userMessageDiv = document.createElement('div');
userMessageDiv.className = 'message user-message';
userMessageDiv.textContent = message;
chatContainer.appendChild(userMessageDiv);
// 显示打字指示器
const typingIndicator = document.getElementById('typing-indicator');
typingIndicator.style.display = 'block';
// 清空输入框
input.value = '';
// 滚动到底部
chatContainer.scrollTop = chatContainer.scrollHeight;
// 发送到服务器
fetch('/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ message: message })
})
.then(response => response.json())
.then(data => {
// 隐藏打字指示器
typingIndicator.style.display = 'none';
// 显示AI回复
const assistantMessageDiv = document.createElement('div');
assistantMessageDiv.className = 'message assistant-message';
assistantMessageDiv.textContent = data.response;
chatContainer.appendChild(assistantMessageDiv);
// 滚动到底部
chatContainer.scrollTop = chatContainer.scrollHeight;
})
.catch(error => {
console.error('Error:', error);
typingIndicator.style.display = 'none';
const errorDiv = document.createElement('div');
errorDiv.className = 'message assistant-message';
errorDiv.textContent = '抱歉,发生了错误: ' + error;
chatContainer.appendChild(errorDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
});
}
// 允许按Enter键发送消息
document.getElementById('user-input').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
sendMessage();
}
});
</script>
</body>
</html>
"""
@app.route('/')
def home():
return render_template_string(HTML_TEMPLATE, messages=messages[1:]) # 跳过系统消息
@app.route('/chat', methods=['POST'])
def chat():
user_message = request.json.get('message')
if not user_message:
return jsonify({"error": "消息不能为空"}), 400
# 添加用户消息到历史
messages.append({"role": "user", "content": user_message})
try:
# 获取AI回复
response = client.chat.completions.create(
model="deepseek-reasoner",
messages=messages,
stream=False,
)
assistant_output = response.choices[0].message.content
# 添加AI回复到历史
messages.append({"role": "assistant", "content": assistant_output})
return jsonify({"response": assistant_output})
except Exception as e:
return jsonify({"error": str(e)}), 500
if __name__ == '__main__':
# 在局域网中运行,host='0.0.0.0' 允许其他设备访问
app.run(host='0.0.0.0', port=5000, debug=True)