@ai-sdk/togetherai 0.0.0-1c33ba03-20260114162300 → 0.0.0-4115c213-20260122152721
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +71 -4
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/docs/24-togetherai.mdx +365 -0
- package/package.json +16 -7
- package/src/index.ts +9 -0
- package/src/reranking/togetherai-reranking-api.ts +43 -0
- package/src/reranking/togetherai-reranking-model.ts +101 -0
- package/src/reranking/togetherai-reranking-options.ts +27 -0
- package/src/togetherai-chat-options.ts +36 -0
- package/src/togetherai-completion-options.ts +9 -0
- package/src/togetherai-embedding-options.ts +11 -0
- package/src/togetherai-image-model.ts +188 -0
- package/src/togetherai-image-settings.ts +18 -0
- package/src/togetherai-provider.ts +180 -0
- package/src/version.ts +6 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { ImageModelV3, SharedV3Warning } from '@ai-sdk/provider';
|
|
2
|
+
import {
|
|
3
|
+
combineHeaders,
|
|
4
|
+
convertImageModelFileToDataUri,
|
|
5
|
+
createJsonResponseHandler,
|
|
6
|
+
createJsonErrorResponseHandler,
|
|
7
|
+
FetchFunction,
|
|
8
|
+
InferSchema,
|
|
9
|
+
lazySchema,
|
|
10
|
+
parseProviderOptions,
|
|
11
|
+
postJsonToApi,
|
|
12
|
+
zodSchema,
|
|
13
|
+
} from '@ai-sdk/provider-utils';
|
|
14
|
+
import { TogetherAIImageModelId } from './togetherai-image-settings';
|
|
15
|
+
import { z } from 'zod/v4';
|
|
16
|
+
|
|
17
|
+
interface TogetherAIImageModelConfig {
|
|
18
|
+
provider: string;
|
|
19
|
+
baseURL: string;
|
|
20
|
+
headers: () => Record<string, string>;
|
|
21
|
+
fetch?: FetchFunction;
|
|
22
|
+
_internal?: {
|
|
23
|
+
currentDate?: () => Date;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class TogetherAIImageModel implements ImageModelV3 {
|
|
28
|
+
readonly specificationVersion = 'v3';
|
|
29
|
+
readonly maxImagesPerCall = 1;
|
|
30
|
+
|
|
31
|
+
get provider(): string {
|
|
32
|
+
return this.config.provider;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
constructor(
|
|
36
|
+
readonly modelId: TogetherAIImageModelId,
|
|
37
|
+
private config: TogetherAIImageModelConfig,
|
|
38
|
+
) {}
|
|
39
|
+
|
|
40
|
+
async doGenerate({
|
|
41
|
+
prompt,
|
|
42
|
+
n,
|
|
43
|
+
size,
|
|
44
|
+
seed,
|
|
45
|
+
providerOptions,
|
|
46
|
+
headers,
|
|
47
|
+
abortSignal,
|
|
48
|
+
files,
|
|
49
|
+
mask,
|
|
50
|
+
}: Parameters<ImageModelV3['doGenerate']>[0]): Promise<
|
|
51
|
+
Awaited<ReturnType<ImageModelV3['doGenerate']>>
|
|
52
|
+
> {
|
|
53
|
+
const warnings: Array<SharedV3Warning> = [];
|
|
54
|
+
|
|
55
|
+
if (mask != null) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
'Together AI does not support mask-based image editing. ' +
|
|
58
|
+
'Use FLUX Kontext models (e.g., black-forest-labs/FLUX.1-kontext-pro) ' +
|
|
59
|
+
'with a reference image and descriptive prompt instead.',
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (size != null) {
|
|
64
|
+
warnings.push({
|
|
65
|
+
type: 'unsupported',
|
|
66
|
+
feature: 'aspectRatio',
|
|
67
|
+
details:
|
|
68
|
+
'This model does not support the `aspectRatio` option. Use `size` instead.',
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
73
|
+
|
|
74
|
+
const togetheraiOptions = await parseProviderOptions({
|
|
75
|
+
provider: 'togetherai',
|
|
76
|
+
providerOptions,
|
|
77
|
+
schema: togetheraiImageProviderOptionsSchema,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Handle image input from files
|
|
81
|
+
let imageUrl: string | undefined;
|
|
82
|
+
if (files != null && files.length > 0) {
|
|
83
|
+
imageUrl = convertImageModelFileToDataUri(files[0]);
|
|
84
|
+
|
|
85
|
+
if (files.length > 1) {
|
|
86
|
+
warnings.push({
|
|
87
|
+
type: 'other',
|
|
88
|
+
message:
|
|
89
|
+
'Together AI only supports a single input image. Additional images are ignored.',
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const splitSize = size?.split('x');
|
|
95
|
+
// https://docs.together.ai/reference/post_images-generations
|
|
96
|
+
const { value: response, responseHeaders } = await postJsonToApi({
|
|
97
|
+
url: `${this.config.baseURL}/images/generations`,
|
|
98
|
+
headers: combineHeaders(this.config.headers(), headers),
|
|
99
|
+
body: {
|
|
100
|
+
model: this.modelId,
|
|
101
|
+
prompt,
|
|
102
|
+
seed,
|
|
103
|
+
...(n > 1 ? { n } : {}),
|
|
104
|
+
...(splitSize && {
|
|
105
|
+
width: parseInt(splitSize[0]),
|
|
106
|
+
height: parseInt(splitSize[1]),
|
|
107
|
+
}),
|
|
108
|
+
...(imageUrl != null ? { image_url: imageUrl } : {}),
|
|
109
|
+
response_format: 'base64',
|
|
110
|
+
...(togetheraiOptions ?? {}),
|
|
111
|
+
},
|
|
112
|
+
failedResponseHandler: createJsonErrorResponseHandler({
|
|
113
|
+
errorSchema: togetheraiErrorSchema,
|
|
114
|
+
errorToMessage: data => data.error.message,
|
|
115
|
+
}),
|
|
116
|
+
successfulResponseHandler: createJsonResponseHandler(
|
|
117
|
+
togetheraiImageResponseSchema,
|
|
118
|
+
),
|
|
119
|
+
abortSignal,
|
|
120
|
+
fetch: this.config.fetch,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
images: response.data.map(item => item.b64_json),
|
|
125
|
+
warnings,
|
|
126
|
+
response: {
|
|
127
|
+
timestamp: currentDate,
|
|
128
|
+
modelId: this.modelId,
|
|
129
|
+
headers: responseHeaders,
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// limited version of the schema, focussed on what is needed for the implementation
|
|
136
|
+
// this approach limits breakages when the API changes and increases efficiency
|
|
137
|
+
const togetheraiImageResponseSchema = z.object({
|
|
138
|
+
data: z.array(
|
|
139
|
+
z.object({
|
|
140
|
+
b64_json: z.string(),
|
|
141
|
+
}),
|
|
142
|
+
),
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// limited version of the schema, focussed on what is needed for the implementation
|
|
146
|
+
// this approach limits breakages when the API changes and increases efficiency
|
|
147
|
+
const togetheraiErrorSchema = z.object({
|
|
148
|
+
error: z.object({
|
|
149
|
+
message: z.string(),
|
|
150
|
+
}),
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Provider options schema for Together AI image generation.
|
|
155
|
+
*/
|
|
156
|
+
export const togetheraiImageProviderOptionsSchema = lazySchema(() =>
|
|
157
|
+
zodSchema(
|
|
158
|
+
z
|
|
159
|
+
.object({
|
|
160
|
+
/**
|
|
161
|
+
* Number of generation steps. Higher values can improve quality.
|
|
162
|
+
*/
|
|
163
|
+
steps: z.number().nullish(),
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Guidance scale for image generation.
|
|
167
|
+
*/
|
|
168
|
+
guidance: z.number().nullish(),
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Negative prompt to guide what to avoid.
|
|
172
|
+
*/
|
|
173
|
+
negative_prompt: z.string().nullish(),
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Disable the safety checker for image generation.
|
|
177
|
+
* When true, the API will not reject images flagged as potentially NSFW.
|
|
178
|
+
* Not available for Flux Schnell Free and Flux Pro models.
|
|
179
|
+
*/
|
|
180
|
+
disable_safety_checker: z.boolean().nullish(),
|
|
181
|
+
})
|
|
182
|
+
.passthrough(),
|
|
183
|
+
),
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
export type TogetherAIImageProviderOptions = InferSchema<
|
|
187
|
+
typeof togetheraiImageProviderOptionsSchema
|
|
188
|
+
>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// https://api.together.ai/models
|
|
2
|
+
export type TogetherAIImageModelId =
|
|
3
|
+
// Text-to-image models
|
|
4
|
+
| 'stabilityai/stable-diffusion-xl-base-1.0'
|
|
5
|
+
| 'black-forest-labs/FLUX.1-dev'
|
|
6
|
+
| 'black-forest-labs/FLUX.1-dev-lora'
|
|
7
|
+
| 'black-forest-labs/FLUX.1-schnell'
|
|
8
|
+
| 'black-forest-labs/FLUX.1-canny'
|
|
9
|
+
| 'black-forest-labs/FLUX.1-depth'
|
|
10
|
+
| 'black-forest-labs/FLUX.1-redux'
|
|
11
|
+
| 'black-forest-labs/FLUX.1.1-pro'
|
|
12
|
+
| 'black-forest-labs/FLUX.1-pro'
|
|
13
|
+
| 'black-forest-labs/FLUX.1-schnell-Free'
|
|
14
|
+
// FLUX Kontext models for image editing
|
|
15
|
+
| 'black-forest-labs/FLUX.1-kontext-pro'
|
|
16
|
+
| 'black-forest-labs/FLUX.1-kontext-max'
|
|
17
|
+
| 'black-forest-labs/FLUX.1-kontext-dev'
|
|
18
|
+
| (string & {});
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OpenAICompatibleChatLanguageModel,
|
|
3
|
+
OpenAICompatibleCompletionLanguageModel,
|
|
4
|
+
OpenAICompatibleEmbeddingModel,
|
|
5
|
+
} from '@ai-sdk/openai-compatible';
|
|
6
|
+
import {
|
|
7
|
+
EmbeddingModelV3,
|
|
8
|
+
ImageModelV3,
|
|
9
|
+
LanguageModelV3,
|
|
10
|
+
ProviderV3,
|
|
11
|
+
RerankingModelV3,
|
|
12
|
+
} from '@ai-sdk/provider';
|
|
13
|
+
import {
|
|
14
|
+
FetchFunction,
|
|
15
|
+
loadApiKey,
|
|
16
|
+
withoutTrailingSlash,
|
|
17
|
+
withUserAgentSuffix,
|
|
18
|
+
} from '@ai-sdk/provider-utils';
|
|
19
|
+
import { TogetherAIRerankingModel } from './reranking/togetherai-reranking-model';
|
|
20
|
+
import { TogetherAIRerankingModelId } from './reranking/togetherai-reranking-options';
|
|
21
|
+
import { TogetherAIChatModelId } from './togetherai-chat-options';
|
|
22
|
+
import { TogetherAICompletionModelId } from './togetherai-completion-options';
|
|
23
|
+
import { TogetherAIEmbeddingModelId } from './togetherai-embedding-options';
|
|
24
|
+
import { TogetherAIImageModel } from './togetherai-image-model';
|
|
25
|
+
import { TogetherAIImageModelId } from './togetherai-image-settings';
|
|
26
|
+
import { VERSION } from './version';
|
|
27
|
+
|
|
28
|
+
export interface TogetherAIProviderSettings {
|
|
29
|
+
/**
|
|
30
|
+
TogetherAI API key.
|
|
31
|
+
*/
|
|
32
|
+
apiKey?: string;
|
|
33
|
+
/**
|
|
34
|
+
Base URL for the API calls.
|
|
35
|
+
*/
|
|
36
|
+
baseURL?: string;
|
|
37
|
+
/**
|
|
38
|
+
Custom headers to include in the requests.
|
|
39
|
+
*/
|
|
40
|
+
headers?: Record<string, string>;
|
|
41
|
+
/**
|
|
42
|
+
Custom fetch implementation. You can use it as a middleware to intercept requests,
|
|
43
|
+
or to provide a custom fetch implementation for e.g. testing.
|
|
44
|
+
*/
|
|
45
|
+
fetch?: FetchFunction;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface TogetherAIProvider extends ProviderV3 {
|
|
49
|
+
/**
|
|
50
|
+
Creates a model for text generation.
|
|
51
|
+
*/
|
|
52
|
+
(modelId: TogetherAIChatModelId): LanguageModelV3;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
Creates a chat model for text generation.
|
|
56
|
+
*/
|
|
57
|
+
chatModel(modelId: TogetherAIChatModelId): LanguageModelV3;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
Creates a chat model for text generation.
|
|
61
|
+
*/
|
|
62
|
+
languageModel(modelId: TogetherAIChatModelId): LanguageModelV3;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
Creates a completion model for text generation.
|
|
66
|
+
*/
|
|
67
|
+
completionModel(modelId: TogetherAICompletionModelId): LanguageModelV3;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
Creates a text embedding model for text generation.
|
|
71
|
+
*/
|
|
72
|
+
embeddingModel(modelId: TogetherAIEmbeddingModelId): EmbeddingModelV3;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @deprecated Use `embeddingModel` instead.
|
|
76
|
+
*/
|
|
77
|
+
textEmbeddingModel(modelId: TogetherAIEmbeddingModelId): EmbeddingModelV3;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
Creates a model for image generation.
|
|
81
|
+
*/
|
|
82
|
+
image(modelId: TogetherAIImageModelId): ImageModelV3;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
Creates a model for image generation.
|
|
86
|
+
*/
|
|
87
|
+
imageModel(modelId: TogetherAIImageModelId): ImageModelV3;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Creates a model for reranking.
|
|
91
|
+
*/
|
|
92
|
+
reranking(modelId: TogetherAIRerankingModelId): RerankingModelV3;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Creates a model for reranking.
|
|
96
|
+
*/
|
|
97
|
+
rerankingModel(modelId: TogetherAIRerankingModelId): RerankingModelV3;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function createTogetherAI(
|
|
101
|
+
options: TogetherAIProviderSettings = {},
|
|
102
|
+
): TogetherAIProvider {
|
|
103
|
+
const baseURL = withoutTrailingSlash(
|
|
104
|
+
options.baseURL ?? 'https://api.together.xyz/v1/',
|
|
105
|
+
);
|
|
106
|
+
const getHeaders = () =>
|
|
107
|
+
withUserAgentSuffix(
|
|
108
|
+
{
|
|
109
|
+
Authorization: `Bearer ${loadApiKey({
|
|
110
|
+
apiKey: options.apiKey,
|
|
111
|
+
environmentVariableName: 'TOGETHER_AI_API_KEY',
|
|
112
|
+
description: 'TogetherAI',
|
|
113
|
+
})}`,
|
|
114
|
+
...options.headers,
|
|
115
|
+
},
|
|
116
|
+
`ai-sdk/togetherai/${VERSION}`,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
interface CommonModelConfig {
|
|
120
|
+
provider: string;
|
|
121
|
+
url: ({ path }: { path: string }) => string;
|
|
122
|
+
headers: () => Record<string, string>;
|
|
123
|
+
fetch?: FetchFunction;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const getCommonModelConfig = (modelType: string): CommonModelConfig => ({
|
|
127
|
+
provider: `togetherai.${modelType}`,
|
|
128
|
+
url: ({ path }) => `${baseURL}${path}`,
|
|
129
|
+
headers: getHeaders,
|
|
130
|
+
fetch: options.fetch,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const createChatModel = (modelId: TogetherAIChatModelId) => {
|
|
134
|
+
return new OpenAICompatibleChatLanguageModel(
|
|
135
|
+
modelId,
|
|
136
|
+
getCommonModelConfig('chat'),
|
|
137
|
+
);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const createCompletionModel = (modelId: TogetherAICompletionModelId) =>
|
|
141
|
+
new OpenAICompatibleCompletionLanguageModel(
|
|
142
|
+
modelId,
|
|
143
|
+
getCommonModelConfig('completion'),
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const createEmbeddingModel = (modelId: TogetherAIEmbeddingModelId) =>
|
|
147
|
+
new OpenAICompatibleEmbeddingModel(
|
|
148
|
+
modelId,
|
|
149
|
+
getCommonModelConfig('embedding'),
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
const createImageModel = (modelId: TogetherAIImageModelId) =>
|
|
153
|
+
new TogetherAIImageModel(modelId, {
|
|
154
|
+
...getCommonModelConfig('image'),
|
|
155
|
+
baseURL: baseURL ?? 'https://api.together.xyz/v1/',
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const createRerankingModel = (modelId: TogetherAIRerankingModelId) =>
|
|
159
|
+
new TogetherAIRerankingModel(modelId, {
|
|
160
|
+
...getCommonModelConfig('reranking'),
|
|
161
|
+
baseURL: baseURL ?? 'https://api.together.xyz/v1/',
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const provider = (modelId: TogetherAIChatModelId) => createChatModel(modelId);
|
|
165
|
+
|
|
166
|
+
provider.specificationVersion = 'v3' as const;
|
|
167
|
+
provider.completionModel = createCompletionModel;
|
|
168
|
+
provider.languageModel = createChatModel;
|
|
169
|
+
provider.chatModel = createChatModel;
|
|
170
|
+
provider.embeddingModel = createEmbeddingModel;
|
|
171
|
+
provider.textEmbeddingModel = createEmbeddingModel;
|
|
172
|
+
provider.image = createImageModel;
|
|
173
|
+
provider.imageModel = createImageModel;
|
|
174
|
+
provider.reranking = createRerankingModel;
|
|
175
|
+
provider.rerankingModel = createRerankingModel;
|
|
176
|
+
|
|
177
|
+
return provider;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export const togetherai = createTogetherAI();
|