UNPKG

ai

Version:

AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.

257 lines (210 loc) • 7.23 kB
--- title: convertToModelMessages description: Convert useChat messages to ModelMessages for AI functions (API Reference) --- # `convertToModelMessages()` The `convertToModelMessages` function is used to transform an array of UI messages from the `useChat` hook into an array of `ModelMessage` objects. These `ModelMessage` objects are compatible with AI core functions like `streamText`. ```ts filename="app/api/chat/route.ts" import { convertToModelMessages, createUIMessageStreamResponse, streamText, toUIMessageStream, } from 'ai'; __PROVIDER_IMPORT__; export async function POST(req: Request) { const { messages } = await req.json(); const result = streamText({ model: __MODEL__, messages: await convertToModelMessages(messages), }); return createUIMessageStreamResponse({ stream: toUIMessageStream({ stream: result.stream }), }); } ``` ## Import <Snippet text={`import { convertToModelMessages } from "ai"`} prompt={false} /> ## API Signature ### Parameters <PropertiesTable content={[ { name: 'messages', type: 'Message[]', description: 'An array of UI messages from the useChat hook to be converted', }, { name: 'options', type: '{ tools?: ToolSet, ignoreIncompleteToolCalls?: boolean, convertDataPart?: (part: DataUIPart) => TextPart | FilePart | undefined }', description: 'Optional configuration object. Provide tools to enable multi-modal tool responses. Set ignoreIncompleteToolCalls to true to skip tool calls without results (default: false). Use convertDataPart to transform custom data parts into model-compatible content.', }, ]} /> ### Returns A Promise that resolves to an array of [`ModelMessage`](/docs/reference/ai-sdk-core/model-message) objects. <PropertiesTable content={[ { name: 'Promise<ModelMessage[]>', type: 'Promise', description: 'A Promise that resolves to an array of ModelMessage objects', }, ]} /> ## Tool Approval States `convertToModelMessages` preserves tool approval state from UI messages when converting them back into `ModelMessage`s for a follow-up `generateText` or `streamText` call. - Tool parts in `approval-requested` state become `tool-approval-request` content parts. - Tool parts in `approval-responded` state become `tool-approval-response` content parts, including `reason` when present. - Automatic approval metadata is preserved by forwarding `approval.isAutomatic` to the `tool-approval-request` part. - Denied tool approvals also produce a synthetic `tool-result` with `output: { type: 'execution-denied', reason?: string }`, so the model receives a complete tool lifecycle and can respond to the denial in the next step. ## Multi-modal Tool Responses The `convertToModelMessages` function supports tools that can return multi-modal content. This is useful when tools need to return non-text content like images. ```ts import { tool } from 'ai'; __PROVIDER_IMPORT__; import { z } from 'zod'; const screenshotTool = tool({ inputSchema: z.object({}), execute: async () => 'imgbase64', toModelOutput: ({ output }) => [ { type: 'file-data', data: output, mediaType: 'image/png' }, ], }); const result = streamText({ model: __MODEL__, messages: convertToModelMessages(messages, { tools: { screenshot: screenshotTool, }, }), }); ``` Tools can implement the optional `toModelOutput` method to transform their results into multi-modal content. The content is an array of content parts, where each part has a `type` (e.g., 'text', 'image') and corresponding data. ## Custom Data Part Conversion The `convertToModelMessages` function supports converting custom data parts attached to user messages. This is useful when users need to include additional context (URLs, code files, JSON configs) with their messages. ### Basic Usage By default, data parts in user messages are filtered out during conversion. To include them, provide a `convertDataPart` callback that transforms data parts into text or file parts that the model can understand: ```ts filename="app/api/chat/route.ts" import { convertToModelMessages, createUIMessageStreamResponse, streamText, toUIMessageStream, } from 'ai'; type CustomUIMessage = UIMessage< never, { url: { url: string; title: string; content: string }; 'code-file': { filename: string; code: string; language: string }; } >; export async function POST(req: Request) { const { messages } = await req.json(); const result = streamText({ model: __MODEL__, messages: convertToModelMessages<CustomUIMessage>(messages, { convertDataPart: part => { // Convert URL attachments to text if (part.type === 'data-url') { return { type: 'text', text: `[Reference: ${part.data.title}](${part.data.url})\n\n${part.data.content}`, }; } // Convert code file attachments if (part.type === 'data-code-file') { return { type: 'text', text: `\`\`\`${part.data.language}\n// ${part.data.filename}\n${part.data.code}\n\`\`\``, }; } // Other data parts are ignored }, }), }); return createUIMessageStreamResponse({ stream: toUIMessageStream({ stream: result.stream }), }); } ``` ### Use Cases **Attaching URL Content** Allow users to attach URLs to their messages, with the content fetched and formatted for the model: ```ts // Client side sendMessage({ parts: [ { type: 'text', text: 'Analyze this article' }, { type: 'data-url', data: { url: 'https://example.com/article', title: 'Important Article', content: '...', }, }, ], }); ``` **Including Code Files as Context** Let users reference code files in their conversations: ```ts convertDataPart: part => { if (part.type === 'data-code-file') { return { type: 'text', text: `\`\`\`${part.data.language}\n${part.data.code}\n\`\`\``, }; } }; ``` **Selective Inclusion** Only data parts for which you return a text or file model message part are included, all other data parts are ignored. ```ts const result = convertToModelMessages< UIMessage< unknown, { url: { url: string; title: string }; code: { code: string; language: string }; note: { text: string }; } > >(messages, { convertDataPart: part => { if (part.type === 'data-url') { return { type: 'text', text: `[${part.data.title}](${part.data.url})`, }; } // data-code and data-node are ignored }, }); ``` ### Type Safety The generic parameter ensures full type safety for your custom data parts: ```ts type MyUIMessage = UIMessage< unknown, { url: { url: string; content: string }; config: { key: string; value: string }; } >; // TypeScript knows the exact shape of part.data convertToModelMessages<MyUIMessage>(messages, { convertDataPart: part => { if (part.type === 'data-url') { // part.data is typed as { url: string; content: string } return { type: 'text', text: part.data.url }; } // Return undefined to skip this part }, }); ```