使用 Cloudflare Workers AI 部署 DeepSeek-R1

使用 Cloudflare Workers AI 部署 DeepSeek-R1

DeepSeek-R1 是 DeepSeek(深度求索)开源的大语言模型,在各种基准测试中的表现都优于 OpenAI-o1-mini。而 Cloudflare Workers AI 是运行在 Cloudflare 网络的 serverless GPU AI 服务,允许用户快速低成本部署许多开源模型。

Cloudflare Workers AI 提供了基于 Qwen2.5 从 DeepSeek-R1 中提炼出来的模型:DeepSeek-R1-Distill-Qwen-32B,详细信息见:developers.cloudflare.com/workers-ai/models/deepseek-r1-distill-qwen-32b。

使用教程

  1. 登陆 Cloudflare 后台,进入 Workers

Cloudflare Workers AI

  1. 选择 AI LLM App 模版

选择 AI LLM App 模版

  1. 命名 Worker 后点击部署,随后点击编辑代码

命名 Worker 后点击部署,随后点击编辑代码

  1. 复制粘贴以下代码,代码兼容了 OpenAI /v1/chat/completions 接口格式,可以在适配 ChatGPT 的第三方软件或SDK上直接使用
export default {
    async fetch(request, env) {
        if (request.method === 'POST' && request.url.includes('v1/chat/completions')) {

            // todo 验证 key

            try {
                const requestData = await request.json();

                const { model, messages } = requestData;

                let isSteam = false;
                if (requestData?.stream) {
                    isSteam = true;
                }

                // get the current time in epoch seconds
                const created = Math.floor(Date.now() / 1000);
                const uuid = crypto.randomUUID();

                const stream = await env.AI.run('@cf/deepseek-ai/deepseek-r1-distill-qwen-32b', {
                    messages: messages,
                    stream: isSteam,
                });

                if (isSteam) {
                    // 创建一个转换流 (TransformStream) 以便实现流式返回
                    const { readable, writable } = new TransformStream();
                    const writer = writable.getWriter();
                    const reader = stream.getReader();

                    // 处理流读取数据并逐帧向客户端发送
                    async function processStream() {
                        const decoder = new TextDecoder();
                        const encoder = new TextEncoder();

                        try {
                            while (true) {
                                const { done, value } = await reader.read();
                                if (done) {
                                    break;
                                }

                                // 确保 value 被转换为字符串类型
                                const stringValue = decoder.decode(value);

                                // 处理每行数据
                                const lines = stringValue.split('\n').filter(line => !!line);
                                for (const line of lines) {
                                    // 跳过非 JSON 数据(例如 [DONE] )
                                    if (line.endsWith('data: [DONE]')) {
                                        continue;
                                    }

                                    try {
                                        const json = JSON.parse(line.replace(/^data: /, ''));

                                        const formattedValue =
                                            `data: ${JSON.stringify({
                                                id: uuid,
                                                created,
                                                object: 'chat.completion.chunk',
                                                model,
                                                choices: [
                                                    {
                                                        delta: { content: json.response },
                                                        index: 0,
                                                        finish_reason: null,
                                                    },
                                                ],
                                            })}\n\n`;
                                        const encodedValue = encoder.encode(formattedValue);
                                        await writer.write(encodedValue);
                                    } catch (e) {
                                        console.error('Failed to parse JSON: ', e);
                                    }
                                }
                            }

                            // 发送完成标识
                            await writer.write(encoder.encode('data: [DONE]\n\n'));
                            writer.close();

                        } catch (err) {
                            console.error('Stream processing error: ', err);
                            // 确保 writer 在错误情况下关闭
                            writer.close();
                        }
                    }


                    // 调用处理流函数
                    processStream().catch(err => {
                        console.error('Stream processing error: ', err);
                    });

                    return new Response(readable, {
                        headers: {
                            'content-type': 'text/event-stream',
                            'Cache-Control': 'no-cache',
                            'Connection': 'keep-alive',
                        },
                    });
                } else {
                    return Response.json({
                        id: uuid,
                        model,
                        created,
                        object: 'chat.completion',
                        choices: [
                            {
                                index: 0,
                                message: {
                                    role: 'assistant',
                                    content: stream.response,
                                },
                                finish_reason: 'stop',
                            },
                        ],
                        usage: {
                            prompt_tokens: 0,
                            completion_tokens: 0,
                            total_tokens: 0,
                        },
                    });
                }

            } catch (error) {
                return new Response(JSON.stringify({ error: 'Invalid request' }), {
                    status: 400,
                    headers: { "Content-Type": "application/json" },
                });
            }
        }

        return new Response('Not Found', { status: 404 });
    }
};
  1. 粘贴完后点击部署,复制 *.workers.dev 域名到第三方客户端就可以使用了,完整路径: https://*.workers.dev/v1/chat/completions 注意:workers.dev 域名在国内被 DNS 污染了,没梯子的话需要绑定一下自己的域名

部署

以 OpenCat 为例

  1. 将域名填写到配置中的 OpenAI 自定义API域名,注意如果直接使用 workers.dev 域名,需要关闭 OpenCat 设置中的使用加密DNS

OpenCat配置

  1. 选择任意 OpenAI 的模型即可使用

OpenCat配置

Cloudflare 成本

@cf/deepseek-ai/deepseek-r1-distill-qwen-32b

🚀 推荐稳定梯子
高速专线,解锁 ChatGPT / Claude 等海外服务
前往 JustMySocks