用 JS 和 Python 分别调通你的第一个 AI API

0 阅读7分钟

用 JS 和 Python 分别调通你的第一个 AI API

本文是【前端转 AI 全栈实战】系列第 03 篇。 上一篇:AI 全栈技术全景图:前端需要补什么 | 下一篇:多模型适配:一套代码接 6 家 AI 厂商


这篇文章你会得到什么

前两篇聊了方向和全景图,从这篇开始写代码

今天的目标很简单:用 JS 和 Python 分别调通一个 AI API,各写一个命令行版的 AI 问答机器人。

做完这篇,你就完成了 AI 应用开发的第一步——从"没调过 AI API"变成"调过了"。听起来很小,但很多人就是卡在这一步。


第一步:注册 + 获取 API Key

推荐先用 DeepSeek,理由:

  • 便宜:约 ¥1/百万 input token,比 OpenAI 便宜 10 倍+
  • :国内服务器,延迟低
  • 兼容:完全兼容 OpenAI API 格式,之后切换其他厂商改个 URL 就行

注册流程:

  1. 打开 platform.deepseek.com
  2. 注册账号(手机号即可)
  3. 进入控制台 → API Keys → 创建新 Key
  4. 复制保存好(只显示一次)

新用户通常有免费额度,学习阶段完全够用。

如果你已有 OpenAI 的 Key,也可以直接用。代码一样,只是改一下 Base URL 和 Key。


JS 版:用 Node.js 调 AI API

环境准备

确保你有 Node.js 18+(需要原生 fetch 支持):

node -v  # 确认 >= 18

创建项目

mkdir ai-chat-js && cd ai-chat-js

新建一个 .env 文件存放 API Key:

DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxx

核心代码

新建 chat.mjs

import { readFileSync } from 'fs'
import { createInterface } from 'readline'

// 加载 .env
const env = Object.fromEntries(
  readFileSync('.env', 'utf-8')
    .split('\n')
    .filter(line => line.includes('='))
    .map(line => line.split('=').map(s => s.trim()))
)

const API_KEY = env.DEEPSEEK_API_KEY
const BASE_URL = 'https://api.deepseek.com'

async function callAI(messages) {
  const res = await fetch(`${BASE_URL}/chat/completions`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${API_KEY}`,
    },
    body: JSON.stringify({
      model: 'deepseek-chat',
      messages,
      temperature: 0.7,
      max_tokens: 2000,
    }),
  })

  if (!res.ok) {
    const err = await res.text()
    throw new Error(`API 请求失败 (${res.status}): ${err}`)
  }

  const data = await res.json()
  return data.choices[0].message.content
}

// 交互式聊天
const rl = createInterface({ input: process.stdin, output: process.stdout })
const messages = [{ role: 'system', content: '你是一个有帮助的 AI 助手。' }]

function ask() {
  rl.question('\n你: ', async (input) => {
    if (!input.trim() || input === 'exit') {
      console.log('再见!')
      rl.close()
      return
    }

    messages.push({ role: 'user', content: input })

    try {
      const reply = await callAI(messages)
      console.log(`\nAI: ${reply}`)
      messages.push({ role: 'assistant', content: reply })
    } catch (err) {
      console.error(`\n错误: ${err.message}`)
    }

    ask()
  })
}

console.log('AI 聊天机器人(输入 exit 退出)')
ask()

运行

node chat.mjs

效果:

AI 聊天机器人(输入 exit 退出)

你: 用一句话解释什么是 API

AI: API 是一组预定义的规则和协议,让不同的软件程序能够互相通信和交换数据。

你: 那 AI API 呢

AI: AI API 是专门提供人工智能能力的接口,你发送文本给它,它返回 AI 生成的回复,比如 ChatGPT 的对话接口。

你: exit
再见!

约 50 行代码,你就有了一个支持多轮对话的 AI 聊天机器人。


Python 版:用原生 requests 调同一个 API

环境准备

确保你有 Python 3.11+:

python --version  # 确认 >= 3.11

推荐用 uv 管理 Python 环境(比 pip 快 10 倍):

# 安装 uv(如果没有)
pip install uv

创建项目

mkdir ai-chat-py && cd ai-chat-py

同样新建 .env 文件:

DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxx

安装依赖:

uv pip install requests python-dotenv

核心代码

新建 chat.py

import os
import requests
from dotenv import load_dotenv

load_dotenv()

API_KEY = os.getenv("DEEPSEEK_API_KEY")
BASE_URL = "https://api.deepseek.com"


def call_ai(messages: list) -> str:
    res = requests.post(
        f"{BASE_URL}/chat/completions",
        headers={
            "Content-Type": "application/json",
            "Authorization": f"Bearer {API_KEY}",
        },
        json={
            "model": "deepseek-chat",
            "messages": messages,
            "temperature": 0.7,
            "max_tokens": 2000,
        },
    )
    res.raise_for_status()
    return res.json()["choices"][0]["message"]["content"]


def main():
    print("AI 聊天机器人(输入 exit 退出)")
    messages = [{"role": "system", "content": "你是一个有帮助的 AI 助手。"}]

    while True:
        user_input = input("\n你: ").strip()
        if not user_input or user_input == "exit":
            print("再见!")
            break

        messages.append({"role": "user", "content": user_input})

        try:
            reply = call_ai(messages)
            print(f"\nAI: {reply}")
            messages.append({"role": "assistant", "content": reply})
        except requests.RequestException as err:
            print(f"\n错误: {err}")


if __name__ == "__main__":
    main()

运行

python chat.py

效果和 JS 版一模一样——因为调的是同一个 API


同一个 API,两种语言对比

把关键部分放在一起对比,你会发现它们几乎一样:

请求发送

JS:

const res = await fetch(`${BASE_URL}/chat/completions`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${API_KEY}`,
  },
  body: JSON.stringify({ model, messages, temperature, max_tokens }),
})
const data = await res.json()

Python:

res = requests.post(
    f"{BASE_URL}/chat/completions",
    headers={
        "Content-Type": "application/json",
        "Authorization": f"Bearer {API_KEY}",
    },
    json={"model": model, "messages": messages, "temperature": temperature, "max_tokens": max_tokens},
)
data = res.json()

几乎 1:1 对应。 URL 一样、Header 一样、Body 一样、返回结构一样。差别只在语法层面。

核心差异总结

JS (Node.js)Python
HTTP 请求fetch() 原生requests.post() 第三方库
JSON 序列化JSON.stringify()json= 参数自动处理
异步async/await同步(也可用 httpx 异步)
环境变量手动读 .envpython-dotenv
交互输入readline 模块input() 内置函数
代码行数~50 行~35 行

Python 代码更短,主要因为 input() 是内置的,不需要像 JS 那样用 readline 创建接口。


请求参数详解

不管 JS 还是 Python,发给 AI API 的参数都是同一套:

{
  "model": "deepseek-chat",
  "messages": [
    { "role": "system", "content": "你是一个有帮助的 AI 助手。" },
    { "role": "user", "content": "你好" }
  ],
  "temperature": 0.7,
  "max_tokens": 2000
}

model

指定用哪个模型。不同厂商有不同的模型名:

厂商模型名
DeepSeekdeepseek-chat / deepseek-reasoner
OpenAIgpt-4o / gpt-4o-mini
Claudeclaude-sonnet-4-20250514
通义千问qwen-plus

messages

对话历史数组,每条消息有 rolecontent

  • system:系统指令,告诉 AI 它是谁、怎么回答。放在最前面,只需要一条。
  • user:用户说的话。
  • assistant:AI 之前的回复。多轮对话靠把历史消息都带上。
const messages = [
  { role: 'system', content: '你是一个前端技术专家。' },
  { role: 'user', content: '什么是 SSE?' },
  { role: 'assistant', content: 'SSE 是 Server-Sent Events...' },
  { role: 'user', content: '它和 WebSocket 有什么区别?' },  // 当前问题
]

每次请求都要把完整的对话历史发过去——AI 没有记忆,它靠 messages 数组理解上下文。

temperature

控制回复的"随机性",范围 0-2:

  • 0:最确定,每次回答几乎一样(适合代码生成、JSON 输出)
  • 0.7:适中,有点创造性(日常对话推荐)
  • 1.5+:很随机,可能胡说八道

max_tokens

限制回复的最大长度。1 token ≈ 0.75 个英文单词 ≈ 0.5 个中文字。

设成 2000 大约能输出 1000 字中文,日常够用。设太大会增加成本和延迟。


返回结构

AI API 返回的 JSON 长这样:

{
  "id": "chatcmpl-xxx",
  "object": "chat.completion",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "这是 AI 的回复..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 25,
    "completion_tokens": 150,
    "total_tokens": 175
  }
}

你需要关心的字段:

  • choices[0].message.content —— AI 的回复文本
  • usage.total_tokens —— 本次消耗的 token 数(算钱用)
  • finish_reason —— stop 表示正常结束,length 表示被 max_tokens 截断了

错误处理

调 AI API 常见的错误:

状态码含义处理方式
401API Key 无效或过期检查 Key 是否正确
429请求太频繁(限流)等几秒重试,或降低请求频率
400参数错误(如 token 超限)检查 messages 长度,减少上下文
500服务端错误稍后重试
超时模型生成太慢设置合理的 timeout,或换模型

实际开发中,429(限流)是最常遇到的。后面的文章会专门讲重试机制和降级策略。


计算成本

调一次 AI API 要花多少钱?以 DeepSeek 为例:

模型Input 价格Output 价格
deepseek-chat¥1 / 百万 tokens¥2 / 百万 tokens

一次普通对话大约消耗 500 tokens(input + output),成本约 ¥0.001——千分之一毛钱。

日常开发学习,一天调几百次也就几毛钱。不用担心成本,先跑起来再说。


用 openai SDK 简化代码(可选)

上面的代码用的是原生 HTTP 请求,好处是理解底层原理。实际开发中可以用官方 SDK 简化:

JS 版(openai 包)

npm install openai
import OpenAI from 'openai'

const client = new OpenAI({
  apiKey: process.env.DEEPSEEK_API_KEY,
  baseURL: 'https://api.deepseek.com',
})

const response = await client.chat.completions.create({
  model: 'deepseek-chat',
  messages: [{ role: 'user', content: '你好' }],
})

console.log(response.choices[0].message.content)

Python 版(openai 包)

uv pip install openai
from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com",
)

response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[{"role": "user", "content": "你好"}],
)

print(response.choices[0].message.content)

两个版本几乎一模一样——因为 Python 的 openai 包和 JS 的 openai 包 API 设计是对齐的。

DeepSeek / 通义千问 / Gemini 都兼容 OpenAI 格式,所以用 openai 这个包就能调大部分厂商的 API,只需要换 baseURLapiKey


总结

  1. AI API 本质就是一个 HTTP POST 接口——发 JSON、收 JSON,和你之前调后端接口没区别。
  2. JS 和 Python 调同一个 API,请求参数和返回结构完全一样,只是语法不同。
  3. 核心参数就四个:modelmessagestemperaturemax_tokens
  4. 多轮对话靠把完整历史 messages 数组带上,AI 本身没有记忆。
  5. DeepSeek 一次对话成本约 ¥0.001,学习阶段放心调
  6. openai SDK(JS/Python 都有)可以简化代码,且同时兼容多家厂商。

下一篇,我们来解决一个实际问题:不想绑死一家 AI 厂商,怎么用一套代码同时适配 OpenAI、DeepSeek、Claude、通义千问、Gemini、Ollama 六家?


下一篇预告04 | 多模型适配:一套代码接 6 家 AI 厂商


讨论话题:你调通了第一个 AI API 了吗?用的哪家服务?遇到什么坑?欢迎评论区交流。