You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为服务器DeepSeek服务添加API密钥及Flask代理故障排查

问题:Flask代理Ollama部署的DeepSeek模型时,验证通过后无法转发聊天请求

环境与背景

  • CentOS7.9服务器上用Ollama部署了deepseek-r1:7b和1.5b模型,Nginx将http://127.0.0.1:11434/转发至http://my-ip:8088,Win11客户端(如Cherry Studio)可正常调用API
  • 为服务添加API密钥验证,已将密钥、过期日期、用户IP写入Api_key.txt,内容示例:
$ head Api_key.txt
key-xxyy11,2025/2/24,10.12.100.200
key-xxyy22,2025/3/24,10.12.200.201

遇到的问题

  1. getModels()函数正常,Cherry Studio可获取模型列表
  2. 使用错误API密钥时,Cherry Studio能收到错误提示,验证逻辑生效
  3. 使用正确API密钥时,Cherry Studio无任何响应,无法与DeepSeek模型聊天

代码问题分析

原代码的核心问题有3点:

  1. 消息格式错误:request.json.get('messages')获取的是完整的消息数组,但代码错误地将整个数组作为单条消息的content传入,导致Ollama收到非法格式的请求
  2. 流式响应处理错误:Ollama开启stream: True后返回的是分块SSE响应,原代码用jsonify(response.json())尝试解析成JSON,无法正确转发流式内容,客户端收不到数据
  3. 硬编码模型参数:固定使用deepseek-r1:1.5b模型,忽略了客户端请求中的指定模型

修复后的代码

from flask import Flask, request, jsonify, Response, stream_with_context
import datetime
import csv
import requests
from functools import lru_cache

app = Flask(__name__)

# 缓存API密钥,避免每次请求读取文件
@lru_cache(maxsize=None)
def load_api_keys():
    api_keys = {}
    with open('/path/to/Api_key.txt', mode='r') as file:
        reader = csv.reader(file)
        for row in reader:
            # 存储密钥对应的过期日期和IP
            api_keys[row[0]] = {
                'expiry': row[1],
                'allowed_ip': row[2]
            }
    return api_keys

# 获取模型列表:正常工作,保留原逻辑
@app.route('/deepseek/models', methods=['GET'])
def getModels():
    url = "http://127.0.0.1:11434/v1/models"
    headers = {
        "Content-Type": "application/json"
    }
    response = requests.get(url, headers=headers)

    if response.status_code == 200:
        json_response = response.json()
    else:
        json_response={"Error":"get model list error from deepseek"}

    return jsonify(json_response), response.status_code

# 处理聊天请求:修复流式转发和格式问题
@app.route('/deepseek/chat/completions', methods=['POST'])
def chat():
    # 获取并校验API密钥
    auth_header = request.headers.get('Authorization')
    if not auth_header or not auth_header.startswith('Bearer '):
        return jsonify({"error": "Invalid Authorization header format."}), 401
    
    api_key = auth_header.split(" ")[1]
    api_keys = load_api_keys()
    
    if api_key not in api_keys:
        return jsonify({"error": "Invalid API key."}), 403
    
    key_info = api_keys[api_key]
    expiry_date = datetime.datetime.strptime(key_info['expiry'], "%Y/%m/%d")
    if expiry_date < datetime.datetime.now():
        return jsonify({"error": "API key has expired."}), 403
    
    # 可选:添加IP校验
    # client_ip = request.remote_addr
    # if client_ip != key_info['allowed_ip']:
    #     return jsonify({"error": "IP not allowed."}), 403
    
    # 直接转发客户端的请求参数,不硬编码
    payload = request.json
    # 确保stream参数和客户端一致,或者强制开启
    # payload['stream'] = True
    
    base_url = "http://127.0.0.1:11434/v1/chat/completions"
    headers = {
        "Content-Type": "application/json"
    }
    
    # 发送流式请求到Ollama,使用stream=True
    try:
        response = requests.post(
            base_url,
            headers=headers,
            json=payload,
            stream=True
        )
        response.raise_for_status()
        
        # 流式转发响应给客户端
        return Response(
            stream_with_context(response.iter_content(chunk_size=1024)),
            content_type=response.headers.get('Content-Type'),
            status=response.status_code
        )
    except requests.exceptions.RequestException as e:
        return jsonify({"error": f"Failed to forward request: {str(e)}"}), 500

if __name__ == '__main__':
    print("Proxy service running on 0.0.0.0:8089")
    app.run(host='0.0.0.0', port=8089, debug=True)

修复说明

  1. 缓存API密钥:用lru_cache缓存密钥信息,避免每次请求读取文件,提升效率
  2. 正确转发请求参数:直接使用客户端的messages和model参数,不再硬编码,保证请求格式正确
  3. 流式响应处理:使用stream_with_context和Flask的Response直接转发Ollama的分块SSE响应,客户端能正常接收流式输出
  4. 完善错误处理:添加Authorization头格式校验,捕获请求异常
  5. 可选IP校验:保留IP校验代码注释,需要时可启用

内容的提问来源于stack exchange,提问作者George W

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 10:25:56