@ai-sdk/gmicloud 0.0.0 → 3.0.1
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 +15 -0
- package/LICENSE +13 -0
- package/README.md +48 -2
- package/dist/index.d.ts +62 -0
- package/dist/index.js +113 -0
- package/dist/index.js.map +1 -0
- package/docs/100-gmicloud.mdx +72 -0
- package/package.json +69 -10
- package/src/gmicloud-chat-language-model-options.ts +3 -0
- package/src/gmicloud-chat-language-model.ts +37 -0
- package/src/gmicloud-chat-options.ts +8 -0
- package/src/gmicloud-error.ts +38 -0
- package/src/gmicloud-provider.ts +109 -0
- package/src/index.ts +7 -0
- package/src/version.ts +6 -0
- package/index.js +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# @ai-sdk/gmicloud
|
|
2
|
+
|
|
3
|
+
## 3.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [7fbfc6d]
|
|
8
|
+
- @ai-sdk/provider-utils@5.0.27
|
|
9
|
+
- @ai-sdk/openai-compatible@3.0.30
|
|
10
|
+
|
|
11
|
+
## 3.0.0
|
|
12
|
+
|
|
13
|
+
### Major Changes
|
|
14
|
+
|
|
15
|
+
- 74556f7: feat(gmicloud): add GMI Cloud provider with OpenAI-compatible chat completions and unwrapped error diagnostics
|
package/LICENSE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright 2023 Vercel, Inc.
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,3 +1,49 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AI SDK - GMI Cloud Provider
|
|
2
2
|
|
|
3
|
-
AI SDK
|
|
3
|
+
The **GMI Cloud provider** for the [AI SDK](https://ai-sdk.dev/docs) contains language model support for [GMI Cloud](https://www.gmicloud.ai), offering GPU inference for open-weight models over an OpenAI-compatible API.
|
|
4
|
+
|
|
5
|
+
> **Deploying to Vercel?** With Vercel's AI Gateway you can access GMI Cloud (and hundreds of models from other providers) — no additional packages, API keys, or extra cost. [Get started with AI Gateway](https://vercel.com/ai-gateway).
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
The GMI Cloud provider is available in the `@ai-sdk/gmicloud` module. You can install it with
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm i @ai-sdk/gmicloud
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Provider Instance
|
|
16
|
+
|
|
17
|
+
You can import the default provider instance `gmicloud` from `@ai-sdk/gmicloud`:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { gmicloud } from '@ai-sdk/gmicloud';
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The GMI Cloud API key is read from the `GMI_CLOUD_APIKEY` environment variable by default. For custom configuration, use `createGmicloud`:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { createGmicloud } from '@ai-sdk/gmicloud';
|
|
27
|
+
|
|
28
|
+
const gmicloud = createGmicloud({
|
|
29
|
+
apiKey: process.env.GMI_CLOUD_APIKEY ?? '',
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Language Models
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { gmicloud } from '@ai-sdk/gmicloud';
|
|
37
|
+
import { generateText } from 'ai';
|
|
38
|
+
|
|
39
|
+
const { text } = await generateText({
|
|
40
|
+
model: gmicloud('deepseek-ai/DeepSeek-V4-Flash-0731'),
|
|
41
|
+
prompt: 'What is the capital of France?',
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
GMI Cloud serves an evolving catalog of open-weight models over chat completions, so model ids are typed as `string`. Embedding and image models are not supported.
|
|
46
|
+
|
|
47
|
+
## Error diagnostics
|
|
48
|
+
|
|
49
|
+
GMI Cloud's edge reports a generic banner in `error.message` on rejections and nests the backend engine's diagnostic in `error.details`. This provider unwraps the nested diagnostic, so `AI_APICallError.message` carries the engine's reason (e.g. `The request is invalid: Invalid max_tokens value, the valid range of max_tokens is [1, 393216].`) instead of `Backend request failed with status 400`.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ProviderV4, LanguageModelV4 } from '@ai-sdk/provider';
|
|
2
|
+
import { FetchFunction } from '@ai-sdk/provider-utils';
|
|
3
|
+
import { z } from 'zod/v4';
|
|
4
|
+
|
|
5
|
+
type GmicloudChatModelId = 'deepseek-ai/DeepSeek-V4-Flash-0731' | 'Qwen/Qwen3.8-Max' | 'moonshotai/kimi-k3' | 'zai-org/GLM-5.2-FP8' | 'MiniMaxAI/MiniMax-M3' | (string & {});
|
|
6
|
+
|
|
7
|
+
interface GmicloudProviderSettings {
|
|
8
|
+
/**
|
|
9
|
+
* GMI Cloud API key. Defaults to the `GMI_CLOUD_APIKEY` environment
|
|
10
|
+
* variable (matching GMI's own SDK package).
|
|
11
|
+
*/
|
|
12
|
+
apiKey?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Base URL for the API calls. Defaults to
|
|
15
|
+
* `https://api.gmi-serving.com/v1`.
|
|
16
|
+
*/
|
|
17
|
+
baseURL?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Custom headers to include in the requests.
|
|
20
|
+
*/
|
|
21
|
+
headers?: Record<string, string>;
|
|
22
|
+
/**
|
|
23
|
+
* Custom fetch implementation. You can use it as a middleware to intercept
|
|
24
|
+
* requests, or to provide a custom fetch implementation for e.g. testing.
|
|
25
|
+
*/
|
|
26
|
+
fetch?: FetchFunction;
|
|
27
|
+
}
|
|
28
|
+
interface GmicloudProvider extends ProviderV4 {
|
|
29
|
+
/**
|
|
30
|
+
* Creates a GMI Cloud model for text generation.
|
|
31
|
+
*/
|
|
32
|
+
(modelId: GmicloudChatModelId): LanguageModelV4;
|
|
33
|
+
/**
|
|
34
|
+
* Creates a GMI Cloud model for text generation.
|
|
35
|
+
*/
|
|
36
|
+
languageModel(modelId: GmicloudChatModelId): LanguageModelV4;
|
|
37
|
+
/**
|
|
38
|
+
* Creates a GMI Cloud chat model for text generation.
|
|
39
|
+
*/
|
|
40
|
+
chat(modelId: GmicloudChatModelId): LanguageModelV4;
|
|
41
|
+
/**
|
|
42
|
+
* @deprecated Use `embeddingModel` instead.
|
|
43
|
+
*/
|
|
44
|
+
textEmbeddingModel(modelId: string): never;
|
|
45
|
+
}
|
|
46
|
+
declare function createGmicloud(options?: GmicloudProviderSettings): GmicloudProvider;
|
|
47
|
+
declare const gmicloud: GmicloudProvider;
|
|
48
|
+
|
|
49
|
+
declare const gmicloudErrorDataSchema: z.ZodObject<{
|
|
50
|
+
error: z.ZodObject<{
|
|
51
|
+
message: z.ZodString;
|
|
52
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
53
|
+
param: z.ZodOptional<z.ZodNullable<z.ZodAny>>;
|
|
54
|
+
code: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
55
|
+
details: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
56
|
+
}, z.core.$strip>;
|
|
57
|
+
}, z.core.$strip>;
|
|
58
|
+
type GmicloudErrorData = z.infer<typeof gmicloudErrorDataSchema>;
|
|
59
|
+
|
|
60
|
+
declare const VERSION: string;
|
|
61
|
+
|
|
62
|
+
export { type GmicloudErrorData, type GmicloudProvider, type GmicloudProviderSettings, VERSION, createGmicloud, gmicloud };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// src/gmicloud-provider.ts
|
|
2
|
+
import {
|
|
3
|
+
NoSuchModelError
|
|
4
|
+
} from "@ai-sdk/provider";
|
|
5
|
+
import {
|
|
6
|
+
loadApiKey,
|
|
7
|
+
withoutTrailingSlash,
|
|
8
|
+
withUserAgentSuffix
|
|
9
|
+
} from "@ai-sdk/provider-utils";
|
|
10
|
+
|
|
11
|
+
// src/gmicloud-chat-language-model.ts
|
|
12
|
+
import { OpenAICompatibleChatLanguageModel } from "@ai-sdk/openai-compatible";
|
|
13
|
+
import {
|
|
14
|
+
serializeModelOptions,
|
|
15
|
+
WORKFLOW_DESERIALIZE,
|
|
16
|
+
WORKFLOW_SERIALIZE
|
|
17
|
+
} from "@ai-sdk/provider-utils";
|
|
18
|
+
var GmicloudChatLanguageModel = class _GmicloudChatLanguageModel extends OpenAICompatibleChatLanguageModel {
|
|
19
|
+
static [WORKFLOW_SERIALIZE](model) {
|
|
20
|
+
return serializeModelOptions({
|
|
21
|
+
modelId: model.modelId,
|
|
22
|
+
config: model.config
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
static [WORKFLOW_DESERIALIZE](options) {
|
|
26
|
+
return new _GmicloudChatLanguageModel(options.modelId, options.config);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// src/gmicloud-error.ts
|
|
31
|
+
import { secureJsonParse } from "@ai-sdk/provider-utils";
|
|
32
|
+
import { z } from "zod/v4";
|
|
33
|
+
var gmicloudErrorDataSchema = z.object({
|
|
34
|
+
error: z.object({
|
|
35
|
+
message: z.string(),
|
|
36
|
+
type: z.string().nullish(),
|
|
37
|
+
param: z.any().nullish(),
|
|
38
|
+
code: z.union([z.string(), z.number()]).nullish(),
|
|
39
|
+
details: z.string().nullish()
|
|
40
|
+
})
|
|
41
|
+
});
|
|
42
|
+
function unwrapDetailsMessage(details) {
|
|
43
|
+
var _a;
|
|
44
|
+
if (details == null || details === "") {
|
|
45
|
+
return void 0;
|
|
46
|
+
}
|
|
47
|
+
let parsed;
|
|
48
|
+
try {
|
|
49
|
+
parsed = secureJsonParse(details);
|
|
50
|
+
} catch (e) {
|
|
51
|
+
return void 0;
|
|
52
|
+
}
|
|
53
|
+
const message = (_a = parsed == null ? void 0 : parsed.error) == null ? void 0 : _a.message;
|
|
54
|
+
return typeof message === "string" && message.trim() !== "" ? message : void 0;
|
|
55
|
+
}
|
|
56
|
+
var gmicloudErrorStructure = {
|
|
57
|
+
errorSchema: gmicloudErrorDataSchema,
|
|
58
|
+
errorToMessage: (data) => {
|
|
59
|
+
var _a;
|
|
60
|
+
return (_a = unwrapDetailsMessage(data.error.details)) != null ? _a : data.error.message;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// src/version.ts
|
|
65
|
+
var VERSION = true ? "3.0.1" : "0.0.0-test";
|
|
66
|
+
|
|
67
|
+
// src/gmicloud-provider.ts
|
|
68
|
+
function createGmicloud(options = {}) {
|
|
69
|
+
var _a;
|
|
70
|
+
const baseURL = withoutTrailingSlash(
|
|
71
|
+
(_a = options.baseURL) != null ? _a : "https://api.gmi-serving.com/v1"
|
|
72
|
+
);
|
|
73
|
+
const getHeaders = () => withUserAgentSuffix(
|
|
74
|
+
{
|
|
75
|
+
Authorization: `Bearer ${loadApiKey({
|
|
76
|
+
apiKey: options.apiKey,
|
|
77
|
+
environmentVariableName: "GMI_CLOUD_APIKEY",
|
|
78
|
+
description: "GMI Cloud API key"
|
|
79
|
+
})}`,
|
|
80
|
+
...options.headers
|
|
81
|
+
},
|
|
82
|
+
`ai-sdk/gmicloud/${VERSION}`
|
|
83
|
+
);
|
|
84
|
+
const createLanguageModel = (modelId) => {
|
|
85
|
+
return new GmicloudChatLanguageModel(modelId, {
|
|
86
|
+
provider: `gmicloud.chat`,
|
|
87
|
+
url: ({ path }) => `${baseURL}${path}`,
|
|
88
|
+
headers: getHeaders,
|
|
89
|
+
fetch: options.fetch,
|
|
90
|
+
errorStructure: gmicloudErrorStructure,
|
|
91
|
+
includeUsage: true
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
const provider = (modelId) => createLanguageModel(modelId);
|
|
95
|
+
provider.specificationVersion = "v4";
|
|
96
|
+
provider.languageModel = createLanguageModel;
|
|
97
|
+
provider.chat = createLanguageModel;
|
|
98
|
+
provider.embeddingModel = (modelId) => {
|
|
99
|
+
throw new NoSuchModelError({ modelId, modelType: "embeddingModel" });
|
|
100
|
+
};
|
|
101
|
+
provider.textEmbeddingModel = provider.embeddingModel;
|
|
102
|
+
provider.imageModel = (modelId) => {
|
|
103
|
+
throw new NoSuchModelError({ modelId, modelType: "imageModel" });
|
|
104
|
+
};
|
|
105
|
+
return provider;
|
|
106
|
+
}
|
|
107
|
+
var gmicloud = createGmicloud();
|
|
108
|
+
export {
|
|
109
|
+
VERSION,
|
|
110
|
+
createGmicloud,
|
|
111
|
+
gmicloud
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/gmicloud-provider.ts","../src/gmicloud-chat-language-model.ts","../src/gmicloud-error.ts","../src/version.ts"],"sourcesContent":["import {\n NoSuchModelError,\n type LanguageModelV4,\n type ProviderV4,\n} from '@ai-sdk/provider';\nimport {\n loadApiKey,\n withoutTrailingSlash,\n withUserAgentSuffix,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { GmicloudChatLanguageModel } from './gmicloud-chat-language-model';\nimport type { GmicloudChatModelId } from './gmicloud-chat-options';\nimport { gmicloudErrorStructure } from './gmicloud-error';\nimport { VERSION } from './version';\n\nexport interface GmicloudProviderSettings {\n /**\n * GMI Cloud API key. Defaults to the `GMI_CLOUD_APIKEY` environment\n * variable (matching GMI's own SDK package).\n */\n apiKey?: string;\n /**\n * Base URL for the API calls. Defaults to\n * `https://api.gmi-serving.com/v1`.\n */\n baseURL?: string;\n /**\n * Custom headers to include in the requests.\n */\n headers?: Record<string, string>;\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept\n * requests, or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nexport interface GmicloudProvider extends ProviderV4 {\n /**\n * Creates a GMI Cloud model for text generation.\n */\n (modelId: GmicloudChatModelId): LanguageModelV4;\n\n /**\n * Creates a GMI Cloud model for text generation.\n */\n languageModel(modelId: GmicloudChatModelId): LanguageModelV4;\n\n /**\n * Creates a GMI Cloud chat model for text generation.\n */\n chat(modelId: GmicloudChatModelId): LanguageModelV4;\n\n /**\n * @deprecated Use `embeddingModel` instead.\n */\n textEmbeddingModel(modelId: string): never;\n}\n\nexport function createGmicloud(\n options: GmicloudProviderSettings = {},\n): GmicloudProvider {\n const baseURL = withoutTrailingSlash(\n options.baseURL ?? 'https://api.gmi-serving.com/v1',\n );\n const getHeaders = () =>\n withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'GMI_CLOUD_APIKEY',\n description: 'GMI Cloud API key',\n })}`,\n ...options.headers,\n },\n `ai-sdk/gmicloud/${VERSION}`,\n );\n\n const createLanguageModel = (modelId: GmicloudChatModelId) => {\n return new GmicloudChatLanguageModel(modelId, {\n provider: `gmicloud.chat`,\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n errorStructure: gmicloudErrorStructure,\n includeUsage: true,\n });\n };\n\n const provider = (modelId: GmicloudChatModelId) =>\n createLanguageModel(modelId);\n\n provider.specificationVersion = 'v4' as const;\n provider.languageModel = createLanguageModel;\n provider.chat = createLanguageModel;\n\n provider.embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'embeddingModel' });\n };\n provider.textEmbeddingModel = provider.embeddingModel;\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'imageModel' });\n };\n\n return provider;\n}\n\nexport const gmicloud = createGmicloud();\n","import { OpenAICompatibleChatLanguageModel } from '@ai-sdk/openai-compatible';\nimport type { LanguageModelV4 } from '@ai-sdk/provider';\nimport {\n serializeModelOptions,\n WORKFLOW_DESERIALIZE,\n WORKFLOW_SERIALIZE,\n} from '@ai-sdk/provider-utils';\nimport type { GmicloudChatModelId } from './gmicloud-chat-language-model-options';\n\ntype GmicloudChatConfig = ConstructorParameters<\n typeof OpenAICompatibleChatLanguageModel\n>[1];\n\n/**\n * GMI Cloud chat completions over the OpenAI-compatible protocol. The only\n * customization is the error structure (see ./gmicloud-error.ts): GMI's edge\n * nests the backend engine's diagnostic in `error.details`, which the default\n * OpenAI-compatible error handling drops.\n */\nexport class GmicloudChatLanguageModel\n extends OpenAICompatibleChatLanguageModel\n implements LanguageModelV4\n{\n static [WORKFLOW_SERIALIZE](model: GmicloudChatLanguageModel) {\n return serializeModelOptions({\n modelId: model.modelId,\n config: model.config,\n });\n }\n\n static [WORKFLOW_DESERIALIZE](options: {\n modelId: GmicloudChatModelId;\n config: GmicloudChatConfig;\n }) {\n return new GmicloudChatLanguageModel(options.modelId, options.config);\n }\n}\n","import type { ProviderErrorStructure } from '@ai-sdk/openai-compatible';\nimport { secureJsonParse } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\nexport const gmicloudErrorDataSchema = z.object({\n error: z.object({\n message: z.string(),\n type: z.string().nullish(),\n param: z.any().nullish(),\n code: z.union([z.string(), z.number()]).nullish(),\n details: z.string().nullish(),\n }),\n});\n\nexport type GmicloudErrorData = z.infer<typeof gmicloudErrorDataSchema>;\n\nfunction unwrapDetailsMessage(details: string | null | undefined) {\n if (details == null || details === '') {\n return undefined;\n }\n let parsed: unknown;\n try {\n parsed = secureJsonParse(details);\n } catch {\n return undefined;\n }\n const message = (parsed as { error?: { message?: unknown } })?.error?.message;\n return typeof message === 'string' && message.trim() !== ''\n ? message\n : undefined;\n}\n\nexport const gmicloudErrorStructure: ProviderErrorStructure<GmicloudErrorData> =\n {\n errorSchema: gmicloudErrorDataSchema,\n errorToMessage: data =>\n unwrapDetailsMessage(data.error.details) ?? data.error.message,\n };\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n"],"mappings":";AAAA;AAAA,EACE;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;;;ACVP,SAAS,yCAAyC;AAElD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAaA,IAAM,4BAAN,MAAM,mCACH,kCAEV;AAAA,EACE,QAAQ,kBAAkB,EAAE,OAAkC;AAC5D,WAAO,sBAAsB;AAAA,MAC3B,SAAS,MAAM;AAAA,MACf,QAAQ,MAAM;AAAA,IAChB,CAAC;AAAA,EACH;AAAA,EAEA,QAAQ,oBAAoB,EAAE,SAG3B;AACD,WAAO,IAAI,2BAA0B,QAAQ,SAAS,QAAQ,MAAM;AAAA,EACtE;AACF;;;ACnCA,SAAS,uBAAuB;AAChC,SAAS,SAAS;AAEX,IAAM,0BAA0B,EAAE,OAAO;AAAA,EAC9C,OAAO,EAAE,OAAO;AAAA,IACd,SAAS,EAAE,OAAO;AAAA,IAClB,MAAM,EAAE,OAAO,EAAE,QAAQ;AAAA,IACzB,OAAO,EAAE,IAAI,EAAE,QAAQ;AAAA,IACvB,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,QAAQ;AAAA,IAChD,SAAS,EAAE,OAAO,EAAE,QAAQ;AAAA,EAC9B,CAAC;AACH,CAAC;AAID,SAAS,qBAAqB,SAAoC;AAhBlE;AAiBE,MAAI,WAAW,QAAQ,YAAY,IAAI;AACrC,WAAO;AAAA,EACT;AACA,MAAI;AACJ,MAAI;AACF,aAAS,gBAAgB,OAAO;AAAA,EAClC,SAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,WAAW,sCAA8C,UAA9C,mBAAqD;AACtE,SAAO,OAAO,YAAY,YAAY,QAAQ,KAAK,MAAM,KACrD,UACA;AACN;AAEO,IAAM,yBACX;AAAA,EACE,aAAa;AAAA,EACb,gBAAgB,UAAK;AAnCzB;AAoCM,sCAAqB,KAAK,MAAM,OAAO,MAAvC,YAA4C,KAAK,MAAM;AAAA;AAC3D;;;ACnCK,IAAM,UACX,OACI,UACA;;;AHuDC,SAAS,eACd,UAAoC,CAAC,GACnB;AA9DpB;AA+DE,QAAM,UAAU;AAAA,KACd,aAAQ,YAAR,YAAmB;AAAA,EACrB;AACA,QAAM,aAAa,MACjB;AAAA,IACE;AAAA,MACE,eAAe,UAAU,WAAW;AAAA,QAClC,QAAQ,QAAQ;AAAA,QAChB,yBAAyB;AAAA,QACzB,aAAa;AAAA,MACf,CAAC,CAAC;AAAA,MACF,GAAG,QAAQ;AAAA,IACb;AAAA,IACA,mBAAmB,OAAO;AAAA,EAC5B;AAEF,QAAM,sBAAsB,CAAC,YAAiC;AAC5D,WAAO,IAAI,0BAA0B,SAAS;AAAA,MAC5C,UAAU;AAAA,MACV,KAAK,CAAC,EAAE,KAAK,MAAM,GAAG,OAAO,GAAG,IAAI;AAAA,MACpC,SAAS;AAAA,MACT,OAAO,QAAQ;AAAA,MACf,gBAAgB;AAAA,MAChB,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,CAAC,YAChB,oBAAoB,OAAO;AAE7B,WAAS,uBAAuB;AAChC,WAAS,gBAAgB;AACzB,WAAS,OAAO;AAEhB,WAAS,iBAAiB,CAAC,YAAoB;AAC7C,UAAM,IAAI,iBAAiB,EAAE,SAAS,WAAW,iBAAiB,CAAC;AAAA,EACrE;AACA,WAAS,qBAAqB,SAAS;AACvC,WAAS,aAAa,CAAC,YAAoB;AACzC,UAAM,IAAI,iBAAiB,EAAE,SAAS,WAAW,aAAa,CAAC;AAAA,EACjE;AAEA,SAAO;AACT;AAEO,IAAM,WAAW,eAAe;","names":[]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: GMI Cloud
|
|
3
|
+
description: Learn how to use GMI Cloud's models with the AI SDK.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GMI Cloud Provider
|
|
7
|
+
|
|
8
|
+
The [GMI Cloud](https://www.gmicloud.ai) provider offers access to open-weight language models through GMI Cloud's GPU inference platform, over an OpenAI-compatible API.
|
|
9
|
+
|
|
10
|
+
API keys can be obtained from the [GMI Cloud console](https://console.gmicloud.ai).
|
|
11
|
+
|
|
12
|
+
## Setup
|
|
13
|
+
|
|
14
|
+
The GMI Cloud provider is available via the `@ai-sdk/gmicloud` module. You can install it with:
|
|
15
|
+
|
|
16
|
+
<InstallPackages packages="@ai-sdk/gmicloud" />
|
|
17
|
+
|
|
18
|
+
## Provider Instance
|
|
19
|
+
|
|
20
|
+
You can import the default provider instance `gmicloud` from `@ai-sdk/gmicloud`:
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { gmicloud } from '@ai-sdk/gmicloud';
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For custom configuration, you can import `createGmicloud` and create a provider instance with your settings:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { createGmicloud } from '@ai-sdk/gmicloud';
|
|
30
|
+
|
|
31
|
+
const gmicloud = createGmicloud({
|
|
32
|
+
apiKey: process.env.GMI_CLOUD_APIKEY ?? '',
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
You can use the following optional settings to customize the GMI Cloud provider instance:
|
|
37
|
+
|
|
38
|
+
- **baseURL** _string_
|
|
39
|
+
|
|
40
|
+
Use a different URL prefix for API calls.
|
|
41
|
+
The default prefix is `https://api.gmi-serving.com/v1`.
|
|
42
|
+
|
|
43
|
+
- **apiKey** _string_
|
|
44
|
+
|
|
45
|
+
API key that is being sent using the `Authorization` header. It defaults to
|
|
46
|
+
the `GMI_CLOUD_APIKEY` environment variable.
|
|
47
|
+
|
|
48
|
+
- **headers** _Record<string,string>_
|
|
49
|
+
|
|
50
|
+
Custom headers to include in the requests.
|
|
51
|
+
|
|
52
|
+
- **fetch** _FetchFunction_
|
|
53
|
+
|
|
54
|
+
Custom fetch implementation.
|
|
55
|
+
|
|
56
|
+
## Language Models
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { gmicloud } from '@ai-sdk/gmicloud';
|
|
60
|
+
import { generateText } from 'ai';
|
|
61
|
+
|
|
62
|
+
const { text } = await generateText({
|
|
63
|
+
model: gmicloud('deepseek-ai/DeepSeek-V4-Flash-0731'),
|
|
64
|
+
prompt: 'What is the capital of France?',
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
GMI Cloud serves an evolving catalog of open-weight models, so model ids are typed as `string`. Embedding and image models are not supported.
|
|
69
|
+
|
|
70
|
+
## Error diagnostics
|
|
71
|
+
|
|
72
|
+
GMI Cloud's edge reports a generic banner in `error.message` on rejections and nests the backend engine's diagnostic in `error.details`. This provider unwraps the nested diagnostic, so `AI_APICallError.message` carries the engine's reason (e.g. `The request is invalid: Invalid max_tokens value, the valid range of max_tokens is [1, 393216].`) instead of `Backend request failed with status 400`.
|
package/package.json
CHANGED
|
@@ -1,18 +1,77 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/gmicloud",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "AI SDK provider for GMI Cloud",
|
|
5
|
-
"license": "Apache-2.0",
|
|
3
|
+
"version": "3.0.1",
|
|
6
4
|
"type": "module",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
11
9
|
"files": [
|
|
12
|
-
"
|
|
10
|
+
"dist/**/*",
|
|
11
|
+
"docs/**/*",
|
|
12
|
+
"src",
|
|
13
|
+
"!src/**/*.test.ts",
|
|
14
|
+
"!src/**/*.test-d.ts",
|
|
15
|
+
"!src/**/__snapshots__",
|
|
16
|
+
"!src/**/__fixtures__",
|
|
17
|
+
"CHANGELOG.md",
|
|
13
18
|
"README.md"
|
|
14
19
|
],
|
|
20
|
+
"directories": {
|
|
21
|
+
"doc": "./docs"
|
|
22
|
+
},
|
|
23
|
+
"exports": {
|
|
24
|
+
"./package.json": "./package.json",
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js",
|
|
28
|
+
"default": "./dist/index.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@ai-sdk/openai-compatible": "3.0.30",
|
|
33
|
+
"@ai-sdk/provider": "4.0.7",
|
|
34
|
+
"@ai-sdk/provider-utils": "5.0.27"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "22.19.19",
|
|
38
|
+
"tsup": "^8.5.1",
|
|
39
|
+
"typescript": "5.8.3",
|
|
40
|
+
"zod": "3.25.76",
|
|
41
|
+
"@vercel/ai-tsconfig": "0.0.0"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"zod": "^3.25.76 || ^4.1.8"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=22"
|
|
48
|
+
},
|
|
15
49
|
"publishConfig": {
|
|
16
|
-
"access": "public"
|
|
50
|
+
"access": "public",
|
|
51
|
+
"provenance": true
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://ai-sdk.dev/docs",
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "https://github.com/vercel/ai",
|
|
57
|
+
"directory": "packages/gmicloud"
|
|
58
|
+
},
|
|
59
|
+
"bugs": {
|
|
60
|
+
"url": "https://github.com/vercel/ai/issues"
|
|
61
|
+
},
|
|
62
|
+
"keywords": [
|
|
63
|
+
"ai"
|
|
64
|
+
],
|
|
65
|
+
"description": "The **GMI Cloud provider** for the [AI SDK](https://ai-sdk.dev/docs) contains language model support for [GMI Cloud](https://www.gmicloud.ai), offering GPU inference for open-weight models over an OpenAI-compatible API.",
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
|
|
68
|
+
"build:watch": "pnpm clean && tsup --watch",
|
|
69
|
+
"clean": "del-cli dist docs *.tsbuildinfo",
|
|
70
|
+
"type-check": "tsc --build",
|
|
71
|
+
"test": "pnpm test:node && pnpm test:edge",
|
|
72
|
+
"test:update": "pnpm test:node -u",
|
|
73
|
+
"test:watch": "vitest --config vitest.node.config.js",
|
|
74
|
+
"test:edge": "vitest --config vitest.edge.config.js --run",
|
|
75
|
+
"test:node": "vitest --config vitest.node.config.js --run"
|
|
17
76
|
}
|
|
18
|
-
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { OpenAICompatibleChatLanguageModel } from '@ai-sdk/openai-compatible';
|
|
2
|
+
import type { LanguageModelV4 } from '@ai-sdk/provider';
|
|
3
|
+
import {
|
|
4
|
+
serializeModelOptions,
|
|
5
|
+
WORKFLOW_DESERIALIZE,
|
|
6
|
+
WORKFLOW_SERIALIZE,
|
|
7
|
+
} from '@ai-sdk/provider-utils';
|
|
8
|
+
import type { GmicloudChatModelId } from './gmicloud-chat-language-model-options';
|
|
9
|
+
|
|
10
|
+
type GmicloudChatConfig = ConstructorParameters<
|
|
11
|
+
typeof OpenAICompatibleChatLanguageModel
|
|
12
|
+
>[1];
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* GMI Cloud chat completions over the OpenAI-compatible protocol. The only
|
|
16
|
+
* customization is the error structure (see ./gmicloud-error.ts): GMI's edge
|
|
17
|
+
* nests the backend engine's diagnostic in `error.details`, which the default
|
|
18
|
+
* OpenAI-compatible error handling drops.
|
|
19
|
+
*/
|
|
20
|
+
export class GmicloudChatLanguageModel
|
|
21
|
+
extends OpenAICompatibleChatLanguageModel
|
|
22
|
+
implements LanguageModelV4
|
|
23
|
+
{
|
|
24
|
+
static [WORKFLOW_SERIALIZE](model: GmicloudChatLanguageModel) {
|
|
25
|
+
return serializeModelOptions({
|
|
26
|
+
modelId: model.modelId,
|
|
27
|
+
config: model.config,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
32
|
+
modelId: GmicloudChatModelId;
|
|
33
|
+
config: GmicloudChatConfig;
|
|
34
|
+
}) {
|
|
35
|
+
return new GmicloudChatLanguageModel(options.modelId, options.config);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ProviderErrorStructure } from '@ai-sdk/openai-compatible';
|
|
2
|
+
import { secureJsonParse } from '@ai-sdk/provider-utils';
|
|
3
|
+
import { z } from 'zod/v4';
|
|
4
|
+
|
|
5
|
+
export const gmicloudErrorDataSchema = z.object({
|
|
6
|
+
error: z.object({
|
|
7
|
+
message: z.string(),
|
|
8
|
+
type: z.string().nullish(),
|
|
9
|
+
param: z.any().nullish(),
|
|
10
|
+
code: z.union([z.string(), z.number()]).nullish(),
|
|
11
|
+
details: z.string().nullish(),
|
|
12
|
+
}),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export type GmicloudErrorData = z.infer<typeof gmicloudErrorDataSchema>;
|
|
16
|
+
|
|
17
|
+
function unwrapDetailsMessage(details: string | null | undefined) {
|
|
18
|
+
if (details == null || details === '') {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
let parsed: unknown;
|
|
22
|
+
try {
|
|
23
|
+
parsed = secureJsonParse(details);
|
|
24
|
+
} catch {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
const message = (parsed as { error?: { message?: unknown } })?.error?.message;
|
|
28
|
+
return typeof message === 'string' && message.trim() !== ''
|
|
29
|
+
? message
|
|
30
|
+
: undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const gmicloudErrorStructure: ProviderErrorStructure<GmicloudErrorData> =
|
|
34
|
+
{
|
|
35
|
+
errorSchema: gmicloudErrorDataSchema,
|
|
36
|
+
errorToMessage: data =>
|
|
37
|
+
unwrapDetailsMessage(data.error.details) ?? data.error.message,
|
|
38
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NoSuchModelError,
|
|
3
|
+
type LanguageModelV4,
|
|
4
|
+
type ProviderV4,
|
|
5
|
+
} from '@ai-sdk/provider';
|
|
6
|
+
import {
|
|
7
|
+
loadApiKey,
|
|
8
|
+
withoutTrailingSlash,
|
|
9
|
+
withUserAgentSuffix,
|
|
10
|
+
type FetchFunction,
|
|
11
|
+
} from '@ai-sdk/provider-utils';
|
|
12
|
+
import { GmicloudChatLanguageModel } from './gmicloud-chat-language-model';
|
|
13
|
+
import type { GmicloudChatModelId } from './gmicloud-chat-options';
|
|
14
|
+
import { gmicloudErrorStructure } from './gmicloud-error';
|
|
15
|
+
import { VERSION } from './version';
|
|
16
|
+
|
|
17
|
+
export interface GmicloudProviderSettings {
|
|
18
|
+
/**
|
|
19
|
+
* GMI Cloud API key. Defaults to the `GMI_CLOUD_APIKEY` environment
|
|
20
|
+
* variable (matching GMI's own SDK package).
|
|
21
|
+
*/
|
|
22
|
+
apiKey?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Base URL for the API calls. Defaults to
|
|
25
|
+
* `https://api.gmi-serving.com/v1`.
|
|
26
|
+
*/
|
|
27
|
+
baseURL?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Custom headers to include in the requests.
|
|
30
|
+
*/
|
|
31
|
+
headers?: Record<string, string>;
|
|
32
|
+
/**
|
|
33
|
+
* Custom fetch implementation. You can use it as a middleware to intercept
|
|
34
|
+
* requests, or to provide a custom fetch implementation for e.g. testing.
|
|
35
|
+
*/
|
|
36
|
+
fetch?: FetchFunction;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface GmicloudProvider extends ProviderV4 {
|
|
40
|
+
/**
|
|
41
|
+
* Creates a GMI Cloud model for text generation.
|
|
42
|
+
*/
|
|
43
|
+
(modelId: GmicloudChatModelId): LanguageModelV4;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Creates a GMI Cloud model for text generation.
|
|
47
|
+
*/
|
|
48
|
+
languageModel(modelId: GmicloudChatModelId): LanguageModelV4;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Creates a GMI Cloud chat model for text generation.
|
|
52
|
+
*/
|
|
53
|
+
chat(modelId: GmicloudChatModelId): LanguageModelV4;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @deprecated Use `embeddingModel` instead.
|
|
57
|
+
*/
|
|
58
|
+
textEmbeddingModel(modelId: string): never;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function createGmicloud(
|
|
62
|
+
options: GmicloudProviderSettings = {},
|
|
63
|
+
): GmicloudProvider {
|
|
64
|
+
const baseURL = withoutTrailingSlash(
|
|
65
|
+
options.baseURL ?? 'https://api.gmi-serving.com/v1',
|
|
66
|
+
);
|
|
67
|
+
const getHeaders = () =>
|
|
68
|
+
withUserAgentSuffix(
|
|
69
|
+
{
|
|
70
|
+
Authorization: `Bearer ${loadApiKey({
|
|
71
|
+
apiKey: options.apiKey,
|
|
72
|
+
environmentVariableName: 'GMI_CLOUD_APIKEY',
|
|
73
|
+
description: 'GMI Cloud API key',
|
|
74
|
+
})}`,
|
|
75
|
+
...options.headers,
|
|
76
|
+
},
|
|
77
|
+
`ai-sdk/gmicloud/${VERSION}`,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const createLanguageModel = (modelId: GmicloudChatModelId) => {
|
|
81
|
+
return new GmicloudChatLanguageModel(modelId, {
|
|
82
|
+
provider: `gmicloud.chat`,
|
|
83
|
+
url: ({ path }) => `${baseURL}${path}`,
|
|
84
|
+
headers: getHeaders,
|
|
85
|
+
fetch: options.fetch,
|
|
86
|
+
errorStructure: gmicloudErrorStructure,
|
|
87
|
+
includeUsage: true,
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const provider = (modelId: GmicloudChatModelId) =>
|
|
92
|
+
createLanguageModel(modelId);
|
|
93
|
+
|
|
94
|
+
provider.specificationVersion = 'v4' as const;
|
|
95
|
+
provider.languageModel = createLanguageModel;
|
|
96
|
+
provider.chat = createLanguageModel;
|
|
97
|
+
|
|
98
|
+
provider.embeddingModel = (modelId: string) => {
|
|
99
|
+
throw new NoSuchModelError({ modelId, modelType: 'embeddingModel' });
|
|
100
|
+
};
|
|
101
|
+
provider.textEmbeddingModel = provider.embeddingModel;
|
|
102
|
+
provider.imageModel = (modelId: string) => {
|
|
103
|
+
throw new NoSuchModelError({ modelId, modelType: 'imageModel' });
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
return provider;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export const gmicloud = createGmicloud();
|
package/src/index.ts
ADDED
package/src/version.ts
ADDED
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|