Skip to content

Commit 325ca55

Browse files
authoredMay 13, 2024··
improve docs & error handling for image parts (#1569)
1 parent 9474d00 commit 325ca55

File tree

8 files changed

+130
-7
lines changed

8 files changed

+130
-7
lines changed
 

Diff for: ‎.changeset/tricky-hotels-check.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@ai-sdk/provider': patch
3+
'ai': patch
4+
---
5+
6+
feat (ai/core): improve image content part error message

Diff for: ‎content/docs/03-ai-sdk-core/03-prompts.mdx

+60-3
Original file line numberDiff line numberDiff line change
@@ -70,21 +70,78 @@ const result = await generateText({
7070

7171
<Note>
7272
Multi-modal refers to interacting with a model across different data types
73-
(text, images, sound etc.).
73+
such as text, image, or audio data.
7474
</Note>
7575

76+
Instead of sending a text in the `content` property, you can send an array of parts that include text and other data types.
77+
Currently image and text parts are supported.
78+
7679
For models that support multi-modal inputs, user messages can include images. An `image` can be a base64-encoded image (`string`), an `ArrayBuffer`, a `Uint8Array`,
7780
a `Buffer`, or a `URL` object. It is possible to mix text and multiple images.
7881

79-
```ts highlight="3-11"
82+
<Note type="warning">
83+
Not all models support all types of multi-modal inputs. Check the model's
84+
capabilities before using this feature.
85+
</Note>
86+
87+
#### Example: Buffer images
88+
89+
```ts highlight="8-11"
8090
const result = await generateText({
8191
model,
8292
messages: [
8393
{
8494
role: 'user',
8595
content: [
8696
{ type: 'text', text: 'Describe the image in detail.' },
87-
{ type: 'image', image: fs.readFileSync('./data/comic-cat.png') },
97+
{
98+
type: 'image',
99+
image: fs.readFileSync('./data/comic-cat.png'),
100+
},
101+
],
102+
},
103+
],
104+
});
105+
```
106+
107+
#### Example: Base-64 encoded images
108+
109+
<Note>You do not need a `data:...` prefix for the base64-encoded image.</Note>
110+
111+
```ts highlight="8-11"
112+
const result = await generateText({
113+
model,
114+
messages: [
115+
{
116+
role: 'user',
117+
content: [
118+
{ type: 'text', text: 'Describe the image in detail.' },
119+
{
120+
type: 'image',
121+
image: fs.readFileSync('./data/comic-cat.png').toString('base64'),
122+
},
123+
],
124+
},
125+
],
126+
});
127+
```
128+
129+
#### Example: Image URLs
130+
131+
```ts highlight="8-13"
132+
const result = await generateText({
133+
model,
134+
messages: [
135+
{
136+
role: 'user',
137+
content: [
138+
{ type: 'text', text: 'Describe the image in detail.' },
139+
{
140+
type: 'image',
141+
image: new URL(
142+
'https://github.com/vercel/ai/blob/main/examples/ai-core/data/comic-cat.png?raw=true',
143+
),
144+
},
88145
],
89146
},
90147
],

Diff for: ‎content/docs/08-troubleshooting/01-common-issues/index.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Common Issues
3-
description: Welcome to the Vercel AI SDK documentation!
3+
description: Troubleshooting information for common issues encountered with the Vercel AI SDK.
44
---
55

66
# Common Issues
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
title: AI_InvalidDataContentError
3+
description: How to fix AI_InvalidDataContentError
4+
---
5+
6+
# AI_InvalidDataContentError
7+
8+
The data content that you have sent in a multi-modal message part is invalid.
9+
10+
Check out the [prompt examples for multi-modal messages](/docs/ai-sdk-core/prompts#multi-modal-messages).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: AI SDK Errors
3+
description: Troubleshooting information for common AI SDK errors.
4+
---
5+
6+
# AI SDK Errors
7+
8+
- [ AI_InvalidDataContentError ](/docs/troubleshooting/ai-sdk-errors/ai-invalid-data-content-error)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { openai } from '@ai-sdk/openai';
2+
import { generateText } from 'ai';
3+
import dotenv from 'dotenv';
4+
import fs from 'node:fs';
5+
6+
dotenv.config();
7+
8+
async function main() {
9+
const result = await generateText({
10+
model: openai.chat('gpt-4-turbo'),
11+
maxTokens: 512,
12+
messages: [
13+
{
14+
role: 'user',
15+
content: [
16+
{ type: 'text', text: 'Describe the image in detail.' },
17+
{
18+
type: 'image',
19+
image: fs.readFileSync('./data/comic-cat.png').toString('base64'),
20+
},
21+
],
22+
},
23+
],
24+
});
25+
26+
console.log(result.text);
27+
}
28+
29+
main().catch(console.error);

Diff for: ‎packages/core/core/prompt/data-content.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,16 @@ export function convertDataContentToUint8Array(
4141
}
4242

4343
if (typeof content === 'string') {
44-
return convertBase64ToUint8Array(content);
44+
try {
45+
return convertBase64ToUint8Array(content);
46+
} catch (error) {
47+
throw new InvalidDataContentError({
48+
message:
49+
'Invalid data content. Content string is not a base64-encoded image.',
50+
content,
51+
cause: error,
52+
});
53+
}
4554
}
4655

4756
if (content instanceof ArrayBuffer) {

Diff for: ‎packages/provider/src/errors/invalid-data-content-error.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
export class InvalidDataContentError extends Error {
22
readonly content: unknown;
3+
readonly cause?: unknown;
34

45
constructor({
56
content,
6-
message = `Invalid data content. Expected a string, Uint8Array, ArrayBuffer, or Buffer, but got ${typeof content}.`,
7+
cause,
8+
message = `Invalid data content. Expected a base64 string, Uint8Array, ArrayBuffer, or Buffer, but got ${typeof content}.`,
79
}: {
810
content: unknown;
11+
cause?: unknown;
912
message?: string;
1013
}) {
1114
super(message);
1215

1316
this.name = 'AI_InvalidDataContentError';
1417

18+
this.cause = cause;
1519
this.content = content;
1620
}
1721

@@ -30,7 +34,7 @@ export class InvalidDataContentError extends Error {
3034
name: this.name,
3135
message: this.message,
3236
stack: this.stack,
33-
37+
cause: this.cause,
3438
content: this.content,
3539
};
3640
}

0 commit comments

Comments
 (0)
Please sign in to comment.