在Next.js Vercel AI项目中添加Together AI作为自定义提供商
使用Vercel AI SDK结合Together AI生成对象(自定义提供商配置)
自定义提供商核心要求(官方文档翻译)
要对接Together AI,需实现符合Vercel AI SDK规范的自定义提供商,核心要点:
- 必须实现
createChatCompletion方法,同时支持流式和非流式两种响应模式 - 完成SDK标准参数与Together AI API参数的映射
- 将Together AI返回的响应格式转换为SDK可识别的结构
- 支持传入API密钥、Base URL等配置项
1. 创建Together AI自定义提供商
新建文件lib/together-ai-provider.ts,实现完整的提供商逻辑:
import { ChatCompletionRequestMessage, ChatCompletionResponse, ChatCompletionStreamResponse, CreateChatCompletionOptions, Provider, } from '@ai-sdk/provider'; // 创建Together AI提供商实例 export function togetherAI(apiKey: string): Provider { return { id: 'together-ai', name: 'Together AI', createChatCompletion: async ( model: string, messages: ChatCompletionRequestMessage[], options: CreateChatCompletionOptions ) => { const { stream, ...restOptions } = options; // 构造Together AI API请求体(兼容OpenAI格式) const requestBody = { model, messages, stream: stream ?? false, ...restOptions, }; // 发送请求到Together AI API const response = await fetch('https://api.together.xyz/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}`, }, body: JSON.stringify(requestBody), }); if (!response.ok) { throw new Error(`Together AI请求失败: ${await response.text()}`); } if (stream) { // 处理流式响应 const stream = response.body; if (!stream) throw new Error('流式响应为空'); return { type: 'stream', stream: new ReadableStream({ async start(controller) { const reader = stream.getReader(); const decoder = new TextDecoder(); try { while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); // 解析Together AI的SSE格式响应 chunk.split('\n').forEach(line => { if (line.startsWith('data: ')) { const data = line.slice(6); if (data === '[DONE]') return; try { const parsed = JSON.parse(data) as ChatCompletionStreamResponse; controller.enqueue(parsed); } catch (e) { console.error('流式响应解析失败:', e); } } }); } } catch (e) { controller.error(e); } finally { controller.close(); } }, }), }; } else { // 处理非流式响应 const data = await response.json() as ChatCompletionResponse; return { type: 'data', data, }; } }, }; }
2. 替换示例中的OpenAI为自定义提供商
参考生成对象的示例,修改后端API路由和前端组件:
2.1 后端API路由(app/api/chat/route.ts)
import { togetherAI } from '@/lib/together-ai-provider'; import { generateObject } from 'ai'; import { z } from 'zod'; export async function POST(req: Request) { const { messages } = await req.json(); const result = await generateObject({ // 指定Together AI模型(示例用Llama 3 70B) model: togetherAI(process.env.TOGETHER_AI_API_KEY!).model('meta-llama/Llama-3-70b-chat-hf'), messages, // 定义要生成的对象结构(与原示例一致) schema: z.object({ name: z.string().describe('用户姓名'), age: z.number().describe('用户年龄'), interests: z.array(z.string()).describe('用户兴趣爱好'), }), }); return Response.json(result); }
2.2 前端组件(app/page.tsx)
核心逻辑与原示例一致,只需确保API调用路径正确:
'use client'; import { useChat } from 'ai/react'; export default function Home() { const { messages, input, handleInputChange, handleSubmit } = useChat({ api: '/api/chat', }); return ( <div className="max-w-md mx-auto p-4"> <h1 className="text-2xl font-bold mb-4">对象生成示例</h1> {messages.map((m) => ( <div key={m.id} className="mb-2 p-2 rounded bg-gray-100"> <strong>{m.role}:</strong> {typeof m.content === 'string' ? m.content : JSON.stringify(m.content, null, 2)} </div> ))} <form onSubmit={handleSubmit} className="mt-4"> <input type="text" value={input} onChange={handleInputChange} placeholder="输入提示词,例如:描述一个喜欢编程和徒步的28岁用户" className="w-full p-2 border rounded" /> <button type="submit" className="mt-2 w-full p-2 bg-blue-500 text-white rounded"> 生成对象 </button> </form> </div> ); }
3. 关键配置与排查
- API密钥:在Vercel项目的环境变量中添加
TOGETHER_AI_API_KEY,值为你的Together AI密钥 - 模型选择:可替换为Together AI支持的其他模型,如
mistralai/Mistral-7B-Instruct-v0.2 - 常见问题:
- 请求失败:检查API密钥是否正确、模型名称是否存在于Together AI的模型列表中
- 格式错误:确认提供商的响应转换逻辑是否正确对齐SDK要求
- 流式卡顿:检查网络连接或Together AI的API速率限制
内容的提问来源于stack exchange,提问作者Pozic
相关产品推荐
相关产品推荐

