🔥 导读:前3篇我们搞定了TS基础语法、Interface和Type,能定义大模型的参数和返回值类型,但大模型开发的核心是「调用API」------而调用API离不开函数和异步操作。今天这篇,带你吃透TS函数的完整定义,结合async/await异步语法,封装一个带类型校验的大模型POST请求函数,学完就能直接复用在项目中,彻底解决"API调用类型混乱"的问题!
适合人群:已掌握TS基础和复杂类型定义,想实现大模型API调用的前端、AI开发新手,全程实战,代码可直接复制运行。
一、先回顾:大模型API调用的核心场景
不管是调用OpenAI、通义千问还是文心一言的API,核心流程都是:
-
定义请求参数(model、messages等);
-
编写POST请求函数,发送请求;
-
接收响应,处理返回结果;
-
处理异步和错误(比如网络错误、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<LLMResponse>:明确函数返回一个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最容易踩的坑
-
异步函数忘记写async/await:导致函数返回Promise对象,无法直接获取响应数据,需记住"异步请求必用async/await";
-
返回值类型定义错误:比如将Promise<LLMResponse>写成LLMResponse,导致TS报错,异步函数的返回值必须是Promise类型;
-
忽略API错误处理:不写try/catch,导致网络错误、API报错时程序崩溃,必须添加错误捕获;
-
类型断言滥用:将response.json()强行断言为LLMResponse,忽略API返回的实际结构,建议先判断响应状态码,再进行类型断言。
六、本篇总结+下一篇预告
✅ 核心收获:学会了TS函数的完整定义(参数+返回值),掌握了async/await异步语法,封装了一个可直接复用、带类型校验、适配多模型的大模型API请求函数;
❌ 避坑提醒:异步函数必加async,返回值类型用Promise,重视错误处理,不滥用类型断言;
📌 下一篇预告:《工程化实战|模块化 + 网络请求:封装企业级 LLM SDK》,带你学会TS模块化开发,封装通用大模型请求类,安全管理API密钥,打造可直接用于企业级项目的LLM工具类!
💡 评论区互动:你平时调用大模型API时,遇到过哪些异步或类型相关的问题?评论区留言,一起解决~