@nordlys-labs/nordlys-ai-provider 0.1.0 → 0.2.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/README.md +102 -3
- package/dist/index.cjs +57 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +111 -4
- package/dist/index.d.ts +111 -4
- package/dist/index.js +57 -35
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -33,6 +33,15 @@ const { text } = await generateText({
|
|
|
33
33
|
model: nordlys('nordlys/hypernova'),
|
|
34
34
|
prompt: 'Explain quantum computing',
|
|
35
35
|
});
|
|
36
|
+
|
|
37
|
+
// With model-level settings
|
|
38
|
+
const { text: creativeText } = await generateText({
|
|
39
|
+
model: nordlys('nordlys/hypernova', {
|
|
40
|
+
temperature: 0.9,
|
|
41
|
+
maxOutputTokens: 2000,
|
|
42
|
+
}),
|
|
43
|
+
prompt: 'Write a creative story',
|
|
44
|
+
});
|
|
36
45
|
```
|
|
37
46
|
|
|
38
47
|
## V3 Content Types
|
|
@@ -49,7 +58,7 @@ content.forEach((item) => {
|
|
|
49
58
|
case 'text': console.log(item.text); break;
|
|
50
59
|
case 'reasoning': console.log(item.text); break;
|
|
51
60
|
case 'file': console.log(item.media_type, item.data); break;
|
|
52
|
-
case 'tool-call': console.log(item.toolName, item.
|
|
61
|
+
case 'tool-call': console.log(item.toolName, item.input); break;
|
|
53
62
|
}
|
|
54
63
|
});
|
|
55
64
|
|
|
@@ -98,16 +107,91 @@ const { text } = await generateText({
|
|
|
98
107
|
|
|
99
108
|
## Configuration
|
|
100
109
|
|
|
110
|
+
### Provider Configuration
|
|
111
|
+
|
|
101
112
|
```ts
|
|
102
113
|
import { createNordlys } from '@nordlys-labs/nordlys-ai-provider';
|
|
103
114
|
|
|
104
|
-
|
|
115
|
+
// Default provider (uses NORDLYS_API_KEY env var)
|
|
116
|
+
const nordlys = createNordlys();
|
|
117
|
+
|
|
118
|
+
// Provider with explicit API key
|
|
119
|
+
const nordlysWithKey = createNordlys({
|
|
120
|
+
apiKey: 'your-api-key-here',
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Provider with custom base URL and API key
|
|
124
|
+
const customNordlys = createNordlys({
|
|
105
125
|
baseURL: 'https://your-api.com/v1',
|
|
106
|
-
apiKey: 'your-key',
|
|
126
|
+
apiKey: 'your-api-key-here',
|
|
107
127
|
headers: { 'Custom-Header': 'value' },
|
|
108
128
|
});
|
|
129
|
+
|
|
130
|
+
// Multiple providers with different API keys
|
|
131
|
+
const provider1 = createNordlys({ apiKey: 'key-for-user-1' });
|
|
132
|
+
const provider2 = createNordlys({ apiKey: 'key-for-user-2' });
|
|
133
|
+
|
|
134
|
+
// Use different providers for different models
|
|
135
|
+
const { text } = await generateText({
|
|
136
|
+
model: provider1('nordlys/hypernova'),
|
|
137
|
+
prompt: 'Hello',
|
|
138
|
+
});
|
|
109
139
|
```
|
|
110
140
|
|
|
141
|
+
**API Key Priority:**
|
|
142
|
+
1. Explicit `apiKey` parameter in `createNordlys()`
|
|
143
|
+
2. `NORDLYS_API_KEY` environment variable (if `apiKey` not provided)
|
|
144
|
+
|
|
145
|
+
### Model Settings
|
|
146
|
+
|
|
147
|
+
You can pass settings when creating a model instance. These settings will be used as defaults for all calls, but can be overridden at call time:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import { nordlys } from '@nordlys-labs/nordlys-ai-provider';
|
|
151
|
+
import { generateText } from 'ai';
|
|
152
|
+
|
|
153
|
+
// Create a model with default settings
|
|
154
|
+
const creativeModel = nordlys('nordlys/hypernova', {
|
|
155
|
+
temperature: 0.9,
|
|
156
|
+
topP: 0.95,
|
|
157
|
+
maxOutputTokens: 2000,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Use the model (settings apply automatically)
|
|
161
|
+
const { text } = await generateText({
|
|
162
|
+
model: creativeModel,
|
|
163
|
+
prompt: 'Write a story',
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Override settings at call time (call-level takes precedence)
|
|
167
|
+
const { text: preciseText } = await generateText({
|
|
168
|
+
model: creativeModel,
|
|
169
|
+
prompt: 'Solve this math problem',
|
|
170
|
+
temperature: 0.1, // Overrides model-level temperature
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Settings can also be passed to languageModel and chat methods
|
|
174
|
+
const model1 = nordlys.languageModel('nordlys/hypernova', {
|
|
175
|
+
temperature: 0.7,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const model2 = nordlys.chat('nordlys/hypernova', {
|
|
179
|
+
temperature: 0.8,
|
|
180
|
+
maxOutputTokens: 1000,
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Available Settings
|
|
185
|
+
|
|
186
|
+
- `temperature?: number` - Sampling temperature
|
|
187
|
+
- `maxOutputTokens?: number` - Maximum tokens to generate
|
|
188
|
+
- `topP?: number` - Top-p sampling parameter
|
|
189
|
+
- `topK?: number` - Top-k sampling parameter (unsupported, will warn)
|
|
190
|
+
- `frequencyPenalty?: number` - Frequency penalty
|
|
191
|
+
- `presencePenalty?: number` - Presence penalty
|
|
192
|
+
- `stopSequences?: string[]` - Stop sequences
|
|
193
|
+
- `providerOptions?: NordlysProviderOptions` - Provider-specific options
|
|
194
|
+
|
|
111
195
|
## Multimodal
|
|
112
196
|
|
|
113
197
|
```ts
|
|
@@ -129,6 +213,7 @@ const { text } = await generateText({
|
|
|
129
213
|
- Streaming with all event types
|
|
130
214
|
- Multimodal inputs (images, audio, PDFs)
|
|
131
215
|
- Enhanced usage tracking
|
|
216
|
+
- Model-level settings support
|
|
132
217
|
- AI SDK standard error handling
|
|
133
218
|
- Full TypeScript support
|
|
134
219
|
|
|
@@ -151,6 +236,20 @@ try {
|
|
|
151
236
|
|
|
152
237
|
## Environment
|
|
153
238
|
|
|
239
|
+
The API key can be provided via environment variable or explicitly when creating the provider:
|
|
240
|
+
|
|
154
241
|
```bash
|
|
242
|
+
# Set environment variable (used as fallback if apiKey not provided)
|
|
155
243
|
export NORDLYS_API_KEY="your-api-key"
|
|
156
244
|
```
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
// Or provide it explicitly when creating the provider
|
|
248
|
+
import { createNordlys } from '@nordlys-labs/nordlys-ai-provider';
|
|
249
|
+
|
|
250
|
+
const nordlys = createNordlys({
|
|
251
|
+
apiKey: process.env.NORDLYS_API_KEY, // Explicit API key takes precedence
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**Note:** If you provide an `apiKey` parameter to `createNordlys()`, it will override the `NORDLYS_API_KEY` environment variable for that provider instance.
|
package/dist/index.cjs
CHANGED
|
@@ -38,17 +38,17 @@ var import_zod2 = require("zod");
|
|
|
38
38
|
var import_provider = require("@ai-sdk/provider");
|
|
39
39
|
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
40
40
|
function convertToolOutput(output) {
|
|
41
|
+
var _a;
|
|
41
42
|
switch (output.type) {
|
|
42
43
|
case "text":
|
|
43
44
|
case "error-text":
|
|
44
45
|
return output.value;
|
|
45
46
|
case "json":
|
|
46
47
|
case "error-json":
|
|
47
|
-
return JSON.stringify(output.value);
|
|
48
48
|
case "content":
|
|
49
49
|
return JSON.stringify(output.value);
|
|
50
50
|
case "execution-denied":
|
|
51
|
-
return "";
|
|
51
|
+
return (_a = output.reason) != null ? _a : "Tool execution denied.";
|
|
52
52
|
default:
|
|
53
53
|
return "";
|
|
54
54
|
}
|
|
@@ -57,6 +57,7 @@ function convertToNordlysChatMessages({
|
|
|
57
57
|
prompt,
|
|
58
58
|
systemMessageMode = "system"
|
|
59
59
|
}) {
|
|
60
|
+
var _a;
|
|
60
61
|
const messages = [];
|
|
61
62
|
const warnings = [];
|
|
62
63
|
for (const { role, content } of prompt) {
|
|
@@ -95,19 +96,23 @@ function convertToNordlysChatMessages({
|
|
|
95
96
|
messages.push({
|
|
96
97
|
role: "user",
|
|
97
98
|
content: content.map((part, index) => {
|
|
98
|
-
var
|
|
99
|
+
var _a2, _b;
|
|
99
100
|
switch (part.type) {
|
|
100
101
|
case "text": {
|
|
101
102
|
return { type: "text", text: part.text };
|
|
102
103
|
}
|
|
103
104
|
case "file": {
|
|
104
|
-
if (
|
|
105
|
+
if (part.data === void 0 || part.data === null) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
"File part data is required but was undefined or null"
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
if ((_a2 = part.mediaType) == null ? void 0 : _a2.startsWith("image/")) {
|
|
105
111
|
const mediaType = part.mediaType === "image/*" ? "image/jpeg" : part.mediaType;
|
|
112
|
+
const url = part.data instanceof URL ? part.data.toString() : `data:${mediaType};base64,${(0, import_provider_utils.convertToBase64)(part.data)}`;
|
|
106
113
|
return {
|
|
107
114
|
type: "image_url",
|
|
108
|
-
image_url: {
|
|
109
|
-
url: part.data instanceof URL ? part.data.toString() : `data:${mediaType};base64,${(0, import_provider_utils.convertToBase64)(part.data)}`
|
|
110
|
-
}
|
|
115
|
+
image_url: { url }
|
|
111
116
|
};
|
|
112
117
|
}
|
|
113
118
|
if (part.mediaType && (part.mediaType === "audio/wav" || part.mediaType === "audio/mp3" || part.mediaType === "audio/mpeg")) {
|
|
@@ -116,10 +121,11 @@ function convertToNordlysChatMessages({
|
|
|
116
121
|
functionality: "audio file parts with URLs"
|
|
117
122
|
});
|
|
118
123
|
}
|
|
124
|
+
const data = typeof part.data === "string" ? part.data : (0, import_provider_utils.convertToBase64)(part.data);
|
|
119
125
|
return {
|
|
120
126
|
type: "input_audio",
|
|
121
127
|
input_audio: {
|
|
122
|
-
data
|
|
128
|
+
data,
|
|
123
129
|
format: part.mediaType === "audio/wav" ? "wav" : "mp3"
|
|
124
130
|
}
|
|
125
131
|
};
|
|
@@ -130,11 +136,12 @@ function convertToNordlysChatMessages({
|
|
|
130
136
|
functionality: "PDF file parts with URLs"
|
|
131
137
|
});
|
|
132
138
|
}
|
|
139
|
+
const base64Data = typeof part.data === "string" ? part.data : (0, import_provider_utils.convertToBase64)(part.data);
|
|
133
140
|
return {
|
|
134
141
|
type: "file",
|
|
135
142
|
file: {
|
|
136
143
|
filename: (_b = part.filename) != null ? _b : `part-${index}.pdf`,
|
|
137
|
-
file_data: `data:application/pdf;base64,${
|
|
144
|
+
file_data: `data:application/pdf;base64,${base64Data}`
|
|
138
145
|
}
|
|
139
146
|
};
|
|
140
147
|
}
|
|
@@ -151,14 +158,14 @@ function convertToNordlysChatMessages({
|
|
|
151
158
|
break;
|
|
152
159
|
}
|
|
153
160
|
case "assistant": {
|
|
154
|
-
|
|
161
|
+
let text = "";
|
|
155
162
|
const reasoningParts = [];
|
|
156
163
|
const generatedFiles = [];
|
|
157
164
|
const toolCalls = [];
|
|
158
165
|
for (const part of content) {
|
|
159
166
|
switch (part.type) {
|
|
160
167
|
case "text": {
|
|
161
|
-
|
|
168
|
+
text += part.text;
|
|
162
169
|
break;
|
|
163
170
|
}
|
|
164
171
|
case "reasoning": {
|
|
@@ -172,7 +179,7 @@ function convertToNordlysChatMessages({
|
|
|
172
179
|
);
|
|
173
180
|
})() : Buffer.from(part.data).toString("base64");
|
|
174
181
|
generatedFiles.push({
|
|
175
|
-
media_type: part.mediaType,
|
|
182
|
+
media_type: (_a = part.mediaType) != null ? _a : "application/octet-stream",
|
|
176
183
|
data: dataString
|
|
177
184
|
});
|
|
178
185
|
break;
|
|
@@ -190,7 +197,6 @@ function convertToNordlysChatMessages({
|
|
|
190
197
|
}
|
|
191
198
|
}
|
|
192
199
|
}
|
|
193
|
-
const text = textParts.join("");
|
|
194
200
|
const reasoning = reasoningParts.join("");
|
|
195
201
|
const message = {
|
|
196
202
|
role: "assistant",
|
|
@@ -204,15 +210,16 @@ function convertToNordlysChatMessages({
|
|
|
204
210
|
}
|
|
205
211
|
case "tool": {
|
|
206
212
|
for (const toolResponse of content) {
|
|
207
|
-
if (toolResponse.type === "tool-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
213
|
+
if (toolResponse.type === "tool-approval-response") {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
const contentValue = convertToolOutput(toolResponse.output);
|
|
217
|
+
if (contentValue) {
|
|
218
|
+
messages.push({
|
|
219
|
+
role: "tool",
|
|
220
|
+
tool_call_id: toolResponse.toolCallId,
|
|
221
|
+
content: contentValue
|
|
222
|
+
});
|
|
216
223
|
}
|
|
217
224
|
}
|
|
218
225
|
break;
|
|
@@ -569,13 +576,14 @@ var nordlysChatChunkSchema = import_zod2.z.union([
|
|
|
569
576
|
})
|
|
570
577
|
]);
|
|
571
578
|
var NordlysChatLanguageModel = class {
|
|
572
|
-
constructor(modelId, config) {
|
|
579
|
+
constructor(modelId, settings, config) {
|
|
573
580
|
this.specificationVersion = "v3";
|
|
574
581
|
this.supportedUrls = {
|
|
575
582
|
"application/pdf": [/^https:\/\/.*$/]
|
|
576
583
|
};
|
|
577
584
|
this.modelId = modelId;
|
|
578
585
|
this.config = config;
|
|
586
|
+
this.settings = settings;
|
|
579
587
|
}
|
|
580
588
|
get provider() {
|
|
581
589
|
return this.config.provider;
|
|
@@ -594,14 +602,28 @@ var NordlysChatLanguageModel = class {
|
|
|
594
602
|
tools,
|
|
595
603
|
toolChoice
|
|
596
604
|
}) {
|
|
605
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
597
606
|
const warnings = [];
|
|
598
|
-
|
|
607
|
+
const mergedMaxOutputTokens = maxOutputTokens != null ? maxOutputTokens : (_a = this.settings) == null ? void 0 : _a.maxOutputTokens;
|
|
608
|
+
const mergedTemperature = temperature != null ? temperature : (_b = this.settings) == null ? void 0 : _b.temperature;
|
|
609
|
+
const mergedTopP = topP != null ? topP : (_c = this.settings) == null ? void 0 : _c.topP;
|
|
610
|
+
const mergedTopK = topK != null ? topK : (_d = this.settings) == null ? void 0 : _d.topK;
|
|
611
|
+
const mergedFrequencyPenalty = frequencyPenalty != null ? frequencyPenalty : (_e = this.settings) == null ? void 0 : _e.frequencyPenalty;
|
|
612
|
+
const mergedPresencePenalty = presencePenalty != null ? presencePenalty : (_f = this.settings) == null ? void 0 : _f.presencePenalty;
|
|
613
|
+
const mergedStopSequences = stopSequences != null ? stopSequences : (_g = this.settings) == null ? void 0 : _g.stopSequences;
|
|
614
|
+
const mergedProviderOptions = {
|
|
615
|
+
...(_h = this.settings) == null ? void 0 : _h.providerOptions,
|
|
616
|
+
...providerOptions
|
|
617
|
+
};
|
|
618
|
+
if (mergedTopK != null) {
|
|
599
619
|
warnings.push({ type: "unsupported", feature: "topK" });
|
|
600
620
|
}
|
|
601
621
|
if (responseFormat != null) {
|
|
602
622
|
warnings.push({ type: "unsupported", feature: "responseFormat" });
|
|
603
623
|
}
|
|
604
|
-
const result = nordlysProviderOptions.safeParse(
|
|
624
|
+
const result = nordlysProviderOptions.safeParse(
|
|
625
|
+
mergedProviderOptions != null ? mergedProviderOptions : {}
|
|
626
|
+
);
|
|
605
627
|
const nordlysOptions = result.success ? result.data : {};
|
|
606
628
|
const {
|
|
607
629
|
tools: nordlysTools,
|
|
@@ -617,13 +639,13 @@ var NordlysChatLanguageModel = class {
|
|
|
617
639
|
const standardizedArgs = {
|
|
618
640
|
messages,
|
|
619
641
|
model: this.modelId,
|
|
620
|
-
max_tokens: typeof
|
|
642
|
+
max_tokens: typeof mergedMaxOutputTokens === "number" ? mergedMaxOutputTokens : void 0,
|
|
621
643
|
max_completion_tokens: nordlysOptions.max_completion_tokens,
|
|
622
|
-
temperature,
|
|
623
|
-
top_p:
|
|
624
|
-
stop:
|
|
625
|
-
presence_penalty:
|
|
626
|
-
frequency_penalty:
|
|
644
|
+
temperature: mergedTemperature,
|
|
645
|
+
top_p: mergedTopP,
|
|
646
|
+
stop: mergedStopSequences,
|
|
647
|
+
presence_penalty: mergedPresencePenalty,
|
|
648
|
+
frequency_penalty: mergedFrequencyPenalty,
|
|
627
649
|
user: nordlysOptions.user,
|
|
628
650
|
tools: nordlysTools,
|
|
629
651
|
tool_choice: nordlysToolChoice
|
|
@@ -1011,7 +1033,7 @@ var NordlysChatLanguageModel = class {
|
|
|
1011
1033
|
// src/nordlys-provider.ts
|
|
1012
1034
|
function createNordlys(options = {}) {
|
|
1013
1035
|
var _a;
|
|
1014
|
-
const baseURL = (_a = (0, import_provider_utils4.withoutTrailingSlash)(options.baseURL)) != null ? _a : "https://
|
|
1036
|
+
const baseURL = (_a = (0, import_provider_utils4.withoutTrailingSlash)(options.baseURL)) != null ? _a : "https://api.nordlyslabs.com/v1";
|
|
1015
1037
|
const getHeaders = () => ({
|
|
1016
1038
|
Authorization: `Bearer ${(0, import_provider_utils4.loadApiKey)({
|
|
1017
1039
|
apiKey: options.apiKey,
|
|
@@ -1021,19 +1043,19 @@ function createNordlys(options = {}) {
|
|
|
1021
1043
|
"Content-Type": "application/json",
|
|
1022
1044
|
...options.headers
|
|
1023
1045
|
});
|
|
1024
|
-
const createChatModel = (modelId) => new NordlysChatLanguageModel(modelId, {
|
|
1046
|
+
const createChatModel = (modelId, settings) => new NordlysChatLanguageModel(modelId, settings, {
|
|
1025
1047
|
provider: "nordlys.chat",
|
|
1026
1048
|
baseURL,
|
|
1027
1049
|
headers: getHeaders,
|
|
1028
1050
|
fetch: options.fetch
|
|
1029
1051
|
});
|
|
1030
|
-
const provider = function(modelId) {
|
|
1052
|
+
const provider = function(modelId, settings) {
|
|
1031
1053
|
if (new.target) {
|
|
1032
1054
|
throw new Error(
|
|
1033
1055
|
"The Nordlys model function cannot be called with the new keyword."
|
|
1034
1056
|
);
|
|
1035
1057
|
}
|
|
1036
|
-
return createChatModel(modelId);
|
|
1058
|
+
return createChatModel(modelId, settings);
|
|
1037
1059
|
};
|
|
1038
1060
|
provider.languageModel = createChatModel;
|
|
1039
1061
|
provider.chat = createChatModel;
|