基于 Node.js 的 API 方式接入深度求索Deepseek、字节跳动豆包大模型

🤔 大模型TOKEN是啥

开始前,我觉得很有必要科普下 token 是啥,这关乎到后面 API 调用的计费方式。

大神通俗解释做的科普视频非常简单接地气地说明了大模型中的 TOKEN 到底是啥👍。跳转地址:B站视频:尝试通俗解释一下:大模型的token究竟是啥

🔌OpenAI SDK

OpenAI SDK(软件开发工具包)是 OpenAI 提供的官方客户端库,主要用于简化调用 OpenAI API 的流程。目前支持多种语言,其中使用最广泛的是 Python SDK 和 Node.js SDK。

国内大多模型都能兼容 OpenAI SDK,这里我也选择使用它来接入 deepseek 跟豆包大模型😄。

OpenAI SDK 能做什么?

功能 说明
Chat Completion 聊天对话、问答、多轮对话
Text Completion 补全文本
Embedding 生成文本向量(用于检索、相似度)
Image Generation 用 DALL·E 生成图像
Speech-to-Text 用 Whisper 将音频转为文本
File 上传/管理 用于 fine-tuning 或向量检索
Assistants API 构建多步智能体(Agent)

🤿 深度求索/Deepseek

目前DeepSeek没有免费额度,调用前需要充值(不过很友好地提供了退款服务😄)。 我们需要创建一个 API key,👉KEY 管理页传送门

使用感受

  • DeepSeek-V3-0324 速度较快,但是资料库很久(截至24年7月),问她今天星期几都能回答2023年11月5日星期日(而且每次答案都可能不一样😂);
  • DeepSeek-R1-0528 速度会慢些(比上述模型慢一倍),答案较为精准,价格也贵些。

🫘豆包大模型

豆包的网站做的真的是好用,实话实说整体就是比 deepseek 的高一个层级😄。以下操作截图基于 2025-07 的官网。

热门模型对比

热门模型对比页面,我们可以看到如下的对比图。

申请KEY

  1. 我们点击API接入会弹出 APIKEY 管理页面,按需新增 KEY 即可。
  2. 实名认证(已认证可跳过)
  3. 选择模型(开通后会有短信提醒)
  4. 查看调用示例,这里选择node.js语言(代码里面有个多余的符号😄)

目前有免费 50W tokens 的福利✌。

推理接入点

在豆包控制台使用大模型时,会有推理接入点这个词,这里简单介绍下是个什么东西

在使用大语言模型进行推理服务时,推理接入点(Endpoint)是模型调用的关键入口。开发者只需通过指定的 ID 即可向大模型发起 API / SDK 推理请求,实现快速接入与灵活调用。系统提供统一的 API 调用方式、调用监控、限流策略与安全保障机制,确保推理过程的稳定性与安全性。

推理接入点类型

  • 预置推理接入点:当用户凭借Model ID调用火山方舟模型时,系统会自动匹配对应模型的预置推理服务;若不存在,则自动创建。适合功能测试与轻量级使用场景。其 Endpoint ID 通常为 ep-m-xxx 格式。
  • 自定义推理接入点:由用户主动创建推理接入点,支持更全面的配置能力,适用于需要精调模型接入、权限控制、算力保障、数据回流等企业级或业务集成场景。 根据接入模型服务的来源,自定义推理接入点分以下两类:
    • 方舟推理接入点:为火山方舟模型服务创建的推理接入点。其 Endpoint ID 通常为 ep-xxx 格式。
    • MLP 推理接入点:为 MLP 推理服务创建的推理接入点。其 Endpoint ID 通常为 ep-s-xxx 格式。

目前(截止到8月31日),字节跳动推出数据协作奖励计划,单模型每日免费50W的tokens,太良心啦!

模型调用监控

👨‍💻完整代码

运行代码前需要安装依赖:pnpm i openai picocolors

控制台问答框架

既然我们都是使用 openAI SDK 调用大模型,是不是可以写一个抽象的聊天交互工具?把用户输入的内容反馈给大模型,输出结果,接着用户继续输入问题。

于是我封装了以下的控制台(基于 node.js 自带 readline 模块)聊天工具,支持流式调用噢。

js 复制代码
import OpenAI from "openai"
import { createInterface } from 'node:readline'
import pc from 'picocolors'

/**
 * @typedef {Object} ModelConfig - 模型配置
 * @property {String} name - 大模型名称
 * @property {String} hit - 输入提示,默认为"请输入:"
 * @property {Boolean} stream - 是否流式响应
 * @property {Number} temperature
 * @property {Number} maxToken - 默认200
 * @property {Array<import("openai/resources").ChatCompletionMessageParam>} messages
 * @property {String} apiKey
 * @property {String} baseURL
 * @property {String} model - 使用的模型标识
 */

/**@returns {ModelConfig} */
const defaultConfig = ()=>({
    hit         : "请输入:",
    stream      : false,
    temperature : 0.7,
    maxToken    : 200,
    messages    : [{ role:'system', content:'你是一个专业的中文AI助理,回答问题简练明了,绝不浪费多一个字' } ],
})

/**
 * @param {ModelConfig} config
 * @param {String} exitCode
 */
export default (config, exitCode='exit')=>{
    config = Object.assign(defaultConfig(), config)

    if(!(config.baseURL && config.apiKey)){
        console.error(pc.red(`请设置 apiKey、baseURL 参数`))
        process.exit(0)
    }

    const ai = new OpenAI({ apiKey: config.apiKey, baseURL: config.baseURL })
    console.debug(pc.gray(`构建 👉${config.name}👈 openai 客户端:URL=${config.baseURL} MODEL=${config.model} STREAM=${config.stream}`))

    const cmd = createInterface({ input: process.stdin, output: process.stdout })

    const ask = ()=> cmd.question(pc.cyan(config.hit), async content=>{
        if(content == exitCode){
            cmd.close()
            console.debug(pc.gray("Bye!"))
            process.exit(0)
        }
        else if(content.trim().length == 0){
            console.debug(pc.gray("不支持空内容噢"))
            ask()
        }
        else{
            const started = Date.now()
            const resp = await ai.chat.completions.create({
                model: config.model,
                messages: [
                    ...config.messages,
                    { role:'user', content }
                ],
                temperature: config.temperature,
                max_completion_tokens: config.maxToken,
                stream: config.stream
            })
            if(!config.stream){
                console.debug(pc.magenta(resp.choices[0].message.content))
            }
            else{
                /**
                 * 流式返回内容
                    {
                        choices: [ { delta: [Object], index: 0 } ],
                        created: 1752564493,
                        id: '0217525644935796745cec05f59d3465a7b2d90de3637dff8b65d',
                        model: 'doubao-seed-1-6-flash-250615',
                        service_tier: 'default',
                        object: 'chat.completion.chunk',
                        usage: null
                    }
                    {
                        choices: [ { delta: [Object], finish_reason: 'stop', index: 0 } ],
                        created: 1752564493,
                        id: '0217525644935796745cec05f59d3465a7b2d90de3637dff8b65d',
                        model: 'doubao-seed-1-6-flash-250615',
                        service_tier: 'default',
                        object: 'chat.completion.chunk',
                        usage: null
                    }
                 */
                for await (const e of resp){
                    /**@type {import("openai/resources").ChatCompletionChunk.Choice} */
                    let d = e.choices[0]
                    if(d && d.delta){
                        process.stdout.write(pc.magenta(d.delta.content))
                        // 纠正输出
                        // if(!!d.finish_reason) console.debug("")
                    }
                }
            }

            console.debug(pc.gray(`${config.stream?"\n":""}used ${((Date.now() - started)/1000).toFixed(1)} s`))
            ask()
        }
    })

    ask()
}

deepseek 调用

js 复制代码
import chat from "./chat.js"

/**
 * model参数:
 *      deepseek-chat        模型指向 DeepSeek-V3-0324
 *      deepseek-reasoner    模型指向 DeepSeek-R1-0528(速度慢些)
 */
chat({
    name: "Deepseek/深度求索",
    apiKey:"{填写你的KEY}",
    baseURL:"https://api.deepseek.com",
    model: "deepseek-chat"
})

豆包调用

js 复制代码
import chat from "./chat.js"

chat({
    stream: true,
    name:"doubao/豆包",
    apiKey:"{填写你的KEY}",
    baseURL:'https://ark.cn-beijing.volces.com/api/v3',
    model: 'doubao-seed-1-6-flash-250615'
    // model: 'doubao-seed-1-6-250615'
})

运行效果

相关推荐
橡晟32 分钟前
深度学习入门:让神经网络变得“深不可测“⚡(二)
人工智能·python·深度学习·机器学习·计算机视觉
墨尘游子32 分钟前
神经网络的层与块
人工智能·python·深度学习·机器学习
Leah010534 分钟前
什么是神经网络,常用的神经网络,如何训练一个神经网络
人工智能·深度学习·神经网络·ai
brzhang35 分钟前
我操,终于有人把 AI 大佬们 PUA 程序员的套路给讲明白了!
前端·后端·架构
止观止1 小时前
React虚拟DOM的进化之路
前端·react.js·前端框架·reactjs·react
goms1 小时前
前端项目集成lint-staged
前端·vue·lint-staged
谢尔登1 小时前
【React Natve】NetworkError 和 TouchableOpacity 组件
前端·react.js·前端框架
PyAIExplorer1 小时前
图像亮度调整的简单实现
人工智能·计算机视觉
Lin Hsüeh-ch'in2 小时前
如何彻底禁用 Chrome 自动更新
前端·chrome
Striker_Eureka2 小时前
DiffDet4SAR——首次将扩散模型用于SAR图像目标检测,来自2024 GRSL(ESI高被引1%论文)
人工智能·目标检测