TypeScript 快速实战系列:函数进阶|TypeScript 函数 + 异步:大模型 API 调用核心

🔥 导读:前3篇我们搞定了TS基础语法、Interface和Type,能定义大模型的参数和返回值类型,但大模型开发的核心是「调用API」------而调用API离不开函数和异步操作。今天这篇,带你吃透TS函数的完整定义,结合async/await异步语法,封装一个带类型校验的大模型POST请求函数,学完就能直接复用在项目中,彻底解决"API调用类型混乱"的问题!

适合人群:已掌握TS基础和复杂类型定义,想实现大模型API调用的前端、AI开发新手,全程实战,代码可直接复制运行。

一、先回顾:大模型API调用的核心场景

不管是调用OpenAI、通义千问还是文心一言的API,核心流程都是:

  1. 定义请求参数(model、messages等);

  2. 编写POST请求函数,发送请求;

  3. 接收响应,处理返回结果;

  4. 处理异步和错误(比如网络错误、API报错)。

用JS写这个流程,容易出现"参数类型错误""返回值盲猜""异步处理混乱"等问题,而TS的函数类型定义+异步语法,能完美解决这些问题,让API调用更安全、更规范。

二、TS函数完整定义:参数+返回值类型(大模型开发必掌握)

大模型API调用函数,必须明确「参数类型」和「返回值类型」,这样既能避免传错参数,又能明确知道返回什么数据,TS的函数定义语法如下:

typescript 复制代码
// 语法:function 函数名(参数1: 类型1, 参数2: 类型2): 返回值类型 { ... }
function 函数名(参数列表): 返回值类型 {
  // 函数体
  return 返回值; // 返回值必须匹配定义的返回值类型
}

1. 基础实战:定义大模型请求参数处理函数

结合上一篇定义的LLMRequest接口,编写一个处理请求参数的函数,确保参数符合类型要求:

typescript 复制代码
// 复用第3篇定义的类型
interface LLMMessage {
  role: 'user' | 'assistant' | 'system';
  content: string;
}

type SupportModel = 'gpt-3.5-turbo' | 'qwen-max';

interface LLMRequest {
  model: SupportModel;
  messages: LLMMessage[];
  temperature?: number;
  stream?: boolean;
}

// 定义参数处理函数:接收原始参数,返回规范的请求参数
function formatLLMRequest(params: LLMRequest): LLMRequest {
  // 处理默认值:如果没传temperature,默认0.7;没传stream,默认false
  return {
    model: params.model,
    messages: params.messages,
    temperature: params.temperature ?? 0.7, // 空值合并运算符
    stream: params.stream ?? false
  };
}

// 调用函数,参数类型错误会直接报错
const rawParams: LLMRequest = {
  model: 'gpt-3.5-turbo',
  messages: [{ role: 'user', content: '处理请求参数' }]
};

const formattedParams = formatLLMRequest(rawParams);
console.log('规范后的请求参数:', formattedParams);

关键:函数参数和返回值都用我们定义的LLMRequest类型,确保输入和输出的类型一致,避免参数混乱。

2. 核心实战:定义大模型API调用函数(同步→异步)

大模型API调用是异步操作(需要等待接口响应),TS中必须用Promise类型定义返回值,结合async/await语法,让异步代码更简洁。

第一步:定义大模型响应类型(复用第3篇的LLMResponse):

typescript 复制代码
interface LLMResponse {
  id: string;
  model: SupportModel;
  choices: Array<{
    message: LLMMessage;
    finish_reason: string;
  }>;
  usage: {
    prompt_tokens: number;
    completion_tokens: number;
    total_tokens: number;
  };
}

第二步:编写异步请求函数,用Promise定义返回值类型:

typescript 复制代码
// 导入node-fetch(用于发送POST请求,需先安装:npm install node-fetch)
import fetch from 'node-fetch';

// 定义大模型API调用函数(异步函数)
async function callLLMApi(params: LLMRequest): Promise<LLMResponse> {
  // 大模型API地址(以OpenAI为例,可替换成通义千问/文心一言地址)
  const apiUrl = 'https://api.openai.com/v1/chat/completions';
  // API密钥(实际开发中建议用环境变量管理)
  const apiKey = 'sk-xxxxxxxxxxxxxxxx';

  try {
    // 发送POST请求,参数需转成JSON字符串
    const response = await fetch(apiUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${apiKey}`
      },
      body: JSON.stringify(params)
    });

    // 解析响应JSON,类型断言为LLMResponse(确保返回值类型正确)
    const data = await response.json() as LLMResponse;
    return data;
  } catch (error) {
    // 错误处理,抛出具体错误信息
    throw new Error(`大模型API调用失败:${(error as Error).message}`);
  }
}

关键说明:

  • async关键字:标记函数为异步函数,函数内部可使用await;

  • Promise&lt;LLMResponse&gt;:明确函数返回一个Promise, resolved后的值是LLMResponse类型;

  • 类型断言as LLMResponse:告诉TS,解析后的response.json()是LLMResponse类型,确保类型安全;

  • try/catch:捕获API调用中的错误(如网络错误、API返回错误),避免程序崩溃。

三、进阶:可选参数、默认参数(适配不同LLM模型)

不同大模型的API参数略有差异(比如有的模型叫max_tokens,有的叫maxLength),我们可以通过「可选参数」和「默认参数」,让函数适配多模型调用。

typescript 复制代码
// 扩展请求参数接口,增加可选参数,适配多模型
interface LLMRequest {
  model: SupportModel;
  messages: LLMMessage[];
  temperature?: number;
  stream?: boolean;
  max_tokens?: number; // OpenAI参数
  maxLength?: number; // 其他模型参数(可选)
}

// 优化API调用函数,增加默认参数和多模型适配
async function callLLMApi(
  params: LLMRequest,
  apiUrl: string = 'https://api.openai.com/v1/chat/completions' // 默认API地址
): Promise<LLMResponse> {
  const apiKey = 'sk-xxxxxxxxxxxxxxxx';

  try {
    // 适配不同模型的参数(示例:如果是通义千问,处理maxLength)
    const requestBody = {
      ...params,
      // 如果是通义千问模型,将maxLength转为max_tokens
      ...(params.model === 'qwen-max' && params.maxLength 
        ? { max_tokens: params.maxLength } 
        : {})
    };

    const response = await fetch(apiUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${apiKey}`
      },
      body: JSON.stringify(requestBody)
    });

    const data = await response.json() as LLMResponse;
    return data;
  } catch (error) {
    throw new Error(`大模型API调用失败:${(error as Error).message}`);
  }
}

// 调用函数:适配通义千问模型,传入maxLength
const qwenParams: LLMRequest = {
  model: 'qwen-max',
  messages: [{ role: 'user', content: '适配多模型参数' }],
  maxLength: 1000
};

callLLMApi(qwenParams, 'https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation');

四、实战产出:可直接复用的TS版大模型请求函数

整合本篇知识点,封装一个「通用、带类型校验、适配多模型」的大模型请求函数,可直接复制到项目中使用:

typescript 复制代码
// 完整可复用的大模型请求函数(整合所有知识点)
import fetch from 'node-fetch';

// 1. 定义基础类型
interface LLMMessage {
  role: 'user' | 'assistant' | 'system';
  content: string;
}

type SupportModel = 'gpt-3.5-turbo' | 'qwen-max' | 'ernie-4.0';

interface LLMRequest {
  model: SupportModel;
  messages: LLMMessage[];
  temperature?: number;
  stream?: boolean;
  max_tokens?: number;
  maxLength?: number;
}

interface LLMResponse {
  id: string;
  model: SupportModel;
  choices: Array<{
    message: LLMMessage;
    finish_reason: string;
  }>;
  usage: {
    prompt_tokens: number;
    completion_tokens: number;
    total_tokens: number;
  };
}

// 2. 格式化请求参数
function formatLLMRequest(params: LLMRequest): LLMRequest {
  return {
    model: params.model,
    messages: params.messages,
    temperature: params.temperature ?? 0.7,
    stream: params.stream ?? false,
    max_tokens: params.max_tokens ?? 1000,
    maxLength: params.maxLength
  };
}

// 3. 通用大模型API调用函数
async function callLLMApi(
  params: LLMRequest,
  apiUrl: string = 'https://api.openai.com/v1/chat/completions'
): Promise<LLMResponse> {
  const apiKey = process.env.LLM_API_KEY || 'sk-xxxxxxxxxxxxxxxx'; // 环境变量管理API密钥

  try {
    // 适配多模型参数
    const requestBody = {
      ...formatLLMRequest(params),
      ...(params.model === 'qwen-max' && params.maxLength 
        ? { max_tokens: params.maxLength } 
        : {})
    };

    const response = await fetch(apiUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${apiKey}`
      },
      body: JSON.stringify(requestBody)
    });

    // 处理API返回的错误(如参数错误、密钥错误)
    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(`API错误:${errorData.error.message}`);
    }

    const data = await response.json() as LLMResponse;
    return data;
  } catch (error) {
    throw new Error(`大模型API调用失败:${(error as Error).message}`);
  }
}

// 4. 测试函数(可直接运行)
async function testLLMApi() {
  try {
    const params: LLMRequest = {
      model: 'gpt-3.5-turbo',
      messages: [
        { role: 'system', content: '你是一个TS开发助手,简洁回答问题' },
        { role: 'user', content: 'TS异步函数如何定义返回值类型?' }
      ],
      temperature: 0.6,
      max_tokens: 200
    };

    const response = await callLLMApi(params);
    console.log('大模型响应:', response.choices[0].message.content);
  } catch (error) {
    console.error('调用失败:', (error as Error).message);
  }
}

// 执行测试
testLLMApi();

使用说明:

  • 安装依赖:运行npm install node\-fetch,用于发送请求;

  • 替换API地址和密钥:根据自己使用的大模型(OpenAI/通义千问)替换apiUrl和apiKey;

  • 环境变量:实际开发中,建议用环境变量管理API密钥,避免硬编码。

五、避坑指南:大模型API调用中TS最容易踩的坑

  1. 异步函数忘记写async/await:导致函数返回Promise对象,无法直接获取响应数据,需记住"异步请求必用async/await";

  2. 返回值类型定义错误:比如将Promise&lt;LLMResponse&gt;写成LLMResponse,导致TS报错,异步函数的返回值必须是Promise类型;

  3. 忽略API错误处理:不写try/catch,导致网络错误、API报错时程序崩溃,必须添加错误捕获;

  4. 类型断言滥用:将response.json()强行断言为LLMResponse,忽略API返回的实际结构,建议先判断响应状态码,再进行类型断言。

六、本篇总结+下一篇预告

✅ 核心收获:学会了TS函数的完整定义(参数+返回值),掌握了async/await异步语法,封装了一个可直接复用、带类型校验、适配多模型的大模型API请求函数;

❌ 避坑提醒:异步函数必加async,返回值类型用Promise,重视错误处理,不滥用类型断言;

📌 下一篇预告:《工程化实战|模块化 + 网络请求:封装企业级 LLM SDK》,带你学会TS模块化开发,封装通用大模型请求类,安全管理API密钥,打造可直接用于企业级项目的LLM工具类!

💡 评论区互动:你平时调用大模型API时,遇到过哪些异步或类型相关的问题?评论区留言,一起解决~

相关推荐
用户52709648744901 天前
前端登录菜单加载性能优化总结
前端
你觉得脆皮鸡好吃吗1 天前
Check Anti-CSRF Token (AI)
前端·网络·网络协议·安全·csrf·网络安全学习
一个快乐的咸鱼1 天前
nextjs接入AI实现流式输出
前端
誰在花里胡哨1 天前
Vue<前端页面装修组件>
前端·vue.js
张元清1 天前
Pareto 动态路由实战:[slug]、catch-all、嵌套布局
前端·javascript·面试
fix一个write十个1 天前
NativeWind v4 与 React Native UI Kit或三方库样式隔离指南
前端·react native
懂懂tty1 天前
React中BeginWork和CompleteWork解析
前端·react.js
_下雨天.1 天前
HAProxy搭建Web群集
前端
梦想CAD控件1 天前
在线CAD开发包图纸转换功能使用指南
前端·javascript·vue.js
亚空间仓鼠1 天前
Ansible之Playbook(三):变量应用
java·前端·ansible