notdiamond 2.0.0-rc1 → 2.0.0-rc11
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 +102 -0
- package/LICENSE +1 -1
- package/README.md +327 -124
- package/client.d.mts +28 -42
- package/client.d.mts.map +1 -1
- package/client.d.ts +28 -42
- package/client.d.ts.map +1 -1
- package/client.js +52 -68
- package/client.js.map +1 -1
- package/client.mjs +50 -66
- package/client.mjs.map +1 -1
- package/core/api-promise.d.mts +2 -2
- package/core/api-promise.d.ts +2 -2
- package/core/error.d.mts +2 -2
- package/core/error.d.ts +2 -2
- package/core/error.js +4 -4
- package/core/error.mjs +2 -2
- package/core/resource.d.mts +3 -3
- package/core/resource.d.ts +3 -3
- package/index.d.mts +3 -3
- package/index.d.ts +3 -3
- package/index.js +4 -4
- package/index.mjs +3 -3
- package/internal/parse.d.mts +2 -2
- package/internal/parse.d.ts +2 -2
- package/internal/shims.js +1 -1
- package/internal/shims.mjs +1 -1
- package/internal/tslib.js +17 -17
- package/internal/uploads.d.mts +4 -4
- package/internal/uploads.d.ts +4 -4
- package/internal/utils/base64.js +2 -2
- package/internal/utils/base64.mjs +3 -3
- package/internal/utils/env.d.mts.map +1 -1
- package/internal/utils/env.d.ts.map +1 -1
- package/internal/utils/env.js +4 -2
- package/internal/utils/env.js.map +1 -1
- package/internal/utils/env.mjs +4 -2
- package/internal/utils/env.mjs.map +1 -1
- package/internal/utils/log.d.mts +3 -3
- package/internal/utils/log.d.ts +3 -3
- package/internal/utils/path.js +1 -1
- package/internal/utils/path.mjs +2 -2
- package/internal/utils/values.js +5 -5
- package/internal/utils/values.mjs +6 -6
- package/package.json +11 -12
- package/resources/custom-router.d.mts +145 -0
- package/resources/custom-router.d.mts.map +1 -0
- package/resources/custom-router.d.ts +145 -0
- package/resources/custom-router.d.ts.map +1 -0
- package/resources/custom-router.js +83 -0
- package/resources/custom-router.js.map +1 -0
- package/resources/custom-router.mjs +79 -0
- package/resources/custom-router.mjs.map +1 -0
- package/resources/index.d.mts +6 -6
- package/resources/index.d.mts.map +1 -1
- package/resources/index.d.ts +6 -6
- package/resources/index.d.ts.map +1 -1
- package/resources/index.js +6 -6
- package/resources/index.js.map +1 -1
- package/resources/index.mjs +3 -3
- package/resources/index.mjs.map +1 -1
- package/resources/model-router.d.mts +196 -0
- package/resources/model-router.d.mts.map +1 -0
- package/resources/model-router.d.ts +196 -0
- package/resources/model-router.d.ts.map +1 -0
- package/resources/model-router.js +70 -0
- package/resources/model-router.js.map +1 -0
- package/resources/model-router.mjs +66 -0
- package/resources/model-router.mjs.map +1 -0
- package/resources/models.d.mts +50 -25
- package/resources/models.d.mts.map +1 -1
- package/resources/models.d.ts +50 -25
- package/resources/models.d.ts.map +1 -1
- package/resources/models.js +5 -0
- package/resources/models.js.map +1 -1
- package/resources/models.mjs +5 -0
- package/resources/models.mjs.map +1 -1
- package/resources/preferences.d.mts +34 -48
- package/resources/preferences.d.mts.map +1 -1
- package/resources/preferences.d.ts +34 -48
- package/resources/preferences.d.ts.map +1 -1
- package/resources/preferences.js +14 -36
- package/resources/preferences.js.map +1 -1
- package/resources/preferences.mjs +14 -36
- package/resources/preferences.mjs.map +1 -1
- package/resources/prompt-adaptation.d.mts +339 -234
- package/resources/prompt-adaptation.d.mts.map +1 -1
- package/resources/prompt-adaptation.d.ts +339 -234
- package/resources/prompt-adaptation.d.ts.map +1 -1
- package/resources/prompt-adaptation.js +30 -53
- package/resources/prompt-adaptation.js.map +1 -1
- package/resources/prompt-adaptation.mjs +30 -53
- package/resources/prompt-adaptation.mjs.map +1 -1
- package/resources/report/index.d.mts +3 -0
- package/resources/report/index.d.mts.map +1 -0
- package/resources/report/index.d.ts +3 -0
- package/resources/report/index.d.ts.map +1 -0
- package/resources/report/index.js +9 -0
- package/resources/report/index.js.map +1 -0
- package/resources/report/index.mjs +4 -0
- package/resources/report/index.mjs.map +1 -0
- package/resources/report/metrics.d.mts +87 -0
- package/resources/report/metrics.d.mts.map +1 -0
- package/resources/report/metrics.d.ts +87 -0
- package/resources/report/metrics.d.ts.map +1 -0
- package/resources/report/metrics.js +57 -0
- package/resources/report/metrics.js.map +1 -0
- package/resources/report/metrics.mjs +53 -0
- package/resources/report/metrics.mjs.map +1 -0
- package/resources/report/report.d.mts +10 -0
- package/resources/report/report.d.mts.map +1 -0
- package/resources/report/report.d.ts +10 -0
- package/resources/report/report.d.ts.map +1 -0
- package/resources/report/report.js +17 -0
- package/resources/report/report.js.map +1 -0
- package/resources/report/report.mjs +12 -0
- package/resources/report/report.mjs.map +1 -0
- package/resources/report.d.mts +1 -244
- package/resources/report.d.mts.map +1 -1
- package/resources/report.d.ts +1 -244
- package/resources/report.d.ts.map +1 -1
- package/resources/report.js +2 -82
- package/resources/report.js.map +1 -1
- package/resources/report.mjs +1 -80
- package/resources/report.mjs.map +1 -1
- package/src/client.ts +80 -131
- package/src/core/api-promise.ts +4 -4
- package/src/core/error.ts +2 -2
- package/src/core/resource.ts +3 -3
- package/src/index.ts +3 -3
- package/src/internal/parse.ts +2 -2
- package/src/internal/shims.ts +1 -1
- package/src/internal/uploads.ts +5 -5
- package/src/internal/utils/base64.ts +3 -3
- package/src/internal/utils/env.ts +4 -2
- package/src/internal/utils/log.ts +3 -3
- package/src/internal/utils/path.ts +2 -2
- package/src/internal/utils/values.ts +6 -6
- package/src/resources/custom-router.ts +168 -0
- package/src/resources/index.ts +23 -34
- package/src/resources/model-router.ts +224 -0
- package/src/resources/models.ts +55 -32
- package/src/resources/preferences.ts +40 -77
- package/src/resources/prompt-adaptation.ts +361 -291
- package/src/resources/report/index.ts +4 -0
- package/src/resources/report/metrics.ts +99 -0
- package/src/resources/report/report.ts +19 -0
- package/src/resources/report.ts +1 -298
- package/src/version.ts +1 -1
- package/version.d.mts +1 -1
- package/version.d.mts.map +1 -1
- package/version.d.ts +1 -1
- package/version.d.ts.map +1 -1
- package/version.js +1 -1
- package/version.js.map +1 -1
- package/version.mjs +1 -1
- package/version.mjs.map +1 -1
- package/resources/admin.d.mts +0 -4
- package/resources/admin.d.mts.map +0 -1
- package/resources/admin.d.ts +0 -4
- package/resources/admin.d.ts.map +0 -1
- package/resources/admin.js +0 -9
- package/resources/admin.js.map +0 -1
- package/resources/admin.mjs +0 -5
- package/resources/admin.mjs.map +0 -1
- package/resources/routing.d.mts +0 -391
- package/resources/routing.d.mts.map +0 -1
- package/resources/routing.d.ts +0 -391
- package/resources/routing.d.ts.map +0 -1
- package/resources/routing.js +0 -163
- package/resources/routing.js.map +0 -1
- package/resources/routing.mjs +0 -159
- package/resources/routing.mjs.map +0 -1
- package/src/resources/admin.ts +0 -5
- package/src/resources/routing.ts +0 -476
package/README.md
CHANGED
|
@@ -1,13 +1,30 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Notdiamond TypeScript API Library
|
|
2
2
|
|
|
3
3
|
[>)](https://npmjs.org/package/notdiamond) 
|
|
4
4
|
|
|
5
|
-
This library provides convenient access to the
|
|
5
|
+
This library provides convenient access to the Notdiamond REST API from server-side TypeScript or JavaScript.
|
|
6
6
|
|
|
7
|
-
The
|
|
7
|
+
The library includes type definitions for all request params and response fields.
|
|
8
8
|
|
|
9
9
|
It is generated with [Stainless](https://www.stainless.com/).
|
|
10
10
|
|
|
11
|
+
## What is Prompt Adaptation?
|
|
12
|
+
|
|
13
|
+
Not Diamond specializes in **Prompt Adaptation** - automatically optimizing your prompts to work optimally across different LLMs. Each language model has unique characteristics, instruction-following patterns, and preferred prompt formats. A prompt that works perfectly for GPT-4 might perform poorly on Claude or Gemini.
|
|
14
|
+
|
|
15
|
+
**The Problem**: Manually rewriting prompts for each model is time-consuming and requires deep expertise in each model's quirks.
|
|
16
|
+
|
|
17
|
+
**The Solution**: Not Diamond automatically adapts your prompts through:
|
|
18
|
+
|
|
19
|
+
- Systematic optimization using your evaluation dataset
|
|
20
|
+
- Automated testing across target models
|
|
21
|
+
- Performance metrics to validate improvements
|
|
22
|
+
- Both system prompt and user message template optimization
|
|
23
|
+
|
|
24
|
+
## Documentation
|
|
25
|
+
|
|
26
|
+
The REST API documentation can be found on [docs.notdiamond.ai](https://docs.notdiamond.ai). The full API of this library can be found in [api.md](api.md).
|
|
27
|
+
|
|
11
28
|
## Installation
|
|
12
29
|
|
|
13
30
|
```sh
|
|
@@ -16,22 +33,127 @@ npm install notdiamond
|
|
|
16
33
|
|
|
17
34
|
## Usage
|
|
18
35
|
|
|
19
|
-
|
|
36
|
+
### Prompt Adaptation
|
|
37
|
+
|
|
38
|
+
Automatically optimize your prompts to work better across different language models. Each model has unique characteristics and preferences - what works well for GPT-4 might not work as well for Claude or Gemini. Prompt Adaptation helps you get optimal performance from each model.
|
|
39
|
+
|
|
40
|
+
#### Quick Start
|
|
20
41
|
|
|
21
42
|
<!-- prettier-ignore -->
|
|
22
|
-
|
|
43
|
+
|
|
44
|
+
```ts
|
|
23
45
|
import NotDiamond from 'notdiamond';
|
|
24
46
|
|
|
25
|
-
const client = new
|
|
47
|
+
const client = new Notdiamond({
|
|
26
48
|
apiKey: process.env['NOT_DIAMOND_API_KEY'], // This is the default and can be omitted
|
|
27
|
-
environment: 'staging', // defaults to 'production'
|
|
28
49
|
});
|
|
29
50
|
|
|
30
|
-
|
|
51
|
+
// Step 1: Start a prompt adaptation job
|
|
52
|
+
const adaptation = await client.prompt.adapt.create({
|
|
53
|
+
fields: ['question'],
|
|
54
|
+
system_prompt: 'You are a helpful assistant that answers questions accurately.',
|
|
55
|
+
target_models: [
|
|
56
|
+
{
|
|
57
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
58
|
+
provider: 'anthropic',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
model: 'gemini-2.5-flash',
|
|
62
|
+
provider: 'google',
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
template: 'Question: {question}\nAnswer:',
|
|
66
|
+
train_goldens: [
|
|
67
|
+
{ fields: { question: 'What is 2+2?' }, answer: '4' },
|
|
68
|
+
{ fields: { question: 'What is the capital of France?' }, answer: 'Paris' },
|
|
69
|
+
{ fields: { question: 'Who wrote Romeo and Juliet?' }, answer: 'William Shakespeare' },
|
|
70
|
+
// Add at least 25 training examples for best results
|
|
71
|
+
// More examples = better adaptation quality
|
|
72
|
+
],
|
|
73
|
+
test_goldens: [
|
|
74
|
+
{ fields: { question: 'What is 3*3?' }, answer: '9' },
|
|
75
|
+
{ fields: { question: 'What is the largest ocean?' }, answer: 'Pacific Ocean' },
|
|
76
|
+
// Add test examples to validate performance
|
|
77
|
+
],
|
|
78
|
+
evaluation_metric: 'LLMaaJ:Sem_Sim_1', // Or use custom evaluation
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
console.log(`Adaptation started: ${adaptation.adaptation_run_id}`);
|
|
82
|
+
|
|
83
|
+
// Step 2: Poll for completion (typically takes 10-30 minutes)
|
|
84
|
+
let status;
|
|
85
|
+
while (true) {
|
|
86
|
+
status = await client.prompt.getAdaptStatus(adaptation.adaptation_run_id);
|
|
87
|
+
console.log(`Status: ${status.status}`);
|
|
88
|
+
|
|
89
|
+
if (status.status === 'queued') {
|
|
90
|
+
console.log(`Queue position: ${status.queue_position}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (status.status === 'completed' || status.status === 'failed') {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
await new Promise(resolve => setTimeout(resolve, 30000)); // Poll every 30 seconds
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Step 3: Get the optimized prompts
|
|
101
|
+
if (status.status === 'completed') {
|
|
102
|
+
const results = await client.prompt.getAdaptResults(adaptation.adaptation_run_id);
|
|
103
|
+
|
|
104
|
+
console.log(`\nOrigin model baseline: ${results.origin_model.score.toFixed(2)}`);
|
|
105
|
+
|
|
106
|
+
for (const target of results.target_models) {
|
|
107
|
+
console.log('\n' + '='.repeat(50));
|
|
108
|
+
console.log(`Model: ${target.model.model} (${target.model.provider})`);
|
|
109
|
+
console.log(`Optimized System Prompt:\n${target.system_prompt}`);
|
|
110
|
+
console.log(`Optimized Template:\n${target.user_message_template}`);
|
|
111
|
+
console.log(`Pre-optimization score: ${target.pre_optimization_score.toFixed(2)}`);
|
|
112
|
+
console.log(`Post-optimization score: ${target.post_optimization_score.toFixed(2)}`);
|
|
113
|
+
console.log(`Improvement: ${((target.post_optimization_score / target.pre_optimization_score - 1) * 100).toFixed(1)}%`);
|
|
114
|
+
console.log(`Cost: $${target.cost.toFixed(4)}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### Key Features
|
|
120
|
+
|
|
121
|
+
- **Automatic Optimization**: Adapts both system prompts and user message templates
|
|
122
|
+
- **Evaluation Metrics**: Choose from standard metrics (semantic similarity, JSON matching, SQL) or provide custom evaluation
|
|
123
|
+
- **Dataset Requirements**: Minimum 25 training examples (more examples = better results)
|
|
124
|
+
- **Processing Time**: Typically 10-30 minutes depending on dataset size and number of target models
|
|
125
|
+
- **Subscription Tiers**: Support for 1-10 target models depending on your plan
|
|
126
|
+
|
|
127
|
+
#### Evaluation Metrics
|
|
128
|
+
|
|
129
|
+
Choose from standard metrics:
|
|
130
|
+
|
|
131
|
+
- `LLMaaJ:Sem_Sim_1`, `LLMaaJ:Sem_Sim_3`, `LLMaaJ:Sem_Sim_10` - Semantic similarity
|
|
132
|
+
- `LLMaaJ:SQL` - SQL query validation
|
|
133
|
+
- `JSON_Match` - JSON structure matching
|
|
134
|
+
|
|
135
|
+
Or provide custom evaluation configuration with your own LLM judge.
|
|
136
|
+
|
|
137
|
+
#### Best Practices
|
|
138
|
+
|
|
139
|
+
1. **Use Representative Examples**: Include diverse examples from your production workload
|
|
140
|
+
2. **Sufficient Dataset Size**: Use at least 25 training examples (50+ recommended)
|
|
141
|
+
3. **Train/Test Split**: Separate train_goldens and test_goldens for proper validation
|
|
142
|
+
4. **A/B Test Results**: Validate optimized prompts in production before full deployment
|
|
143
|
+
|
|
144
|
+
For more details, see the [Prompt Adaptation documentation](https://docs.notdiamond.ai/docs/adapting-prompts-to-new-models).
|
|
145
|
+
|
|
146
|
+
### Model Routing
|
|
147
|
+
|
|
148
|
+
Not Diamond also provides intelligent model routing to select the best model for your query:
|
|
149
|
+
|
|
150
|
+
<!-- prettier-ignore -->
|
|
151
|
+
```ts
|
|
152
|
+
const response = await client.modelRouter.selectModel({
|
|
31
153
|
llm_providers: [
|
|
32
154
|
{ model: 'gpt-4o', provider: 'openai' },
|
|
33
|
-
{ model: 'claude-
|
|
34
|
-
{ model: 'gemini-
|
|
155
|
+
{ model: 'claude-sonnet-4-5-20250929', provider: 'anthropic' },
|
|
156
|
+
{ model: 'gemini-2.5-flash', provider: 'google' },
|
|
35
157
|
],
|
|
36
158
|
messages: [
|
|
37
159
|
{ role: 'system', content: 'You are a helpful assistant.' },
|
|
@@ -48,25 +170,44 @@ This library includes TypeScript definitions for all request params and response
|
|
|
48
170
|
|
|
49
171
|
<!-- prettier-ignore -->
|
|
50
172
|
```ts
|
|
51
|
-
import
|
|
173
|
+
import Notdiamond from 'notdiamond';
|
|
52
174
|
|
|
53
|
-
const client = new
|
|
175
|
+
const client = new Notdiamond({
|
|
54
176
|
apiKey: process.env['NOT_DIAMOND_API_KEY'], // This is the default and can be omitted
|
|
55
|
-
environment: 'staging', // defaults to 'production'
|
|
56
177
|
});
|
|
57
178
|
|
|
58
|
-
const params: NotDiamond.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
{
|
|
179
|
+
const params: NotDiamond.PromptAdaptCreateParams = {
|
|
180
|
+
fields: ['question', 'context'],
|
|
181
|
+
system_prompt: 'You are a helpful assistant.',
|
|
182
|
+
target_models: [
|
|
183
|
+
{
|
|
184
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
185
|
+
provider: 'anthropic',
|
|
186
|
+
},
|
|
63
187
|
],
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
{
|
|
188
|
+
template: 'Context: {context}\nQuestion: {question}\nAnswer:',
|
|
189
|
+
train_goldens: [
|
|
190
|
+
{
|
|
191
|
+
fields: {
|
|
192
|
+
question: 'What is 2+2?',
|
|
193
|
+
context: 'Basic arithmetic',
|
|
194
|
+
},
|
|
195
|
+
answer: '4',
|
|
196
|
+
},
|
|
197
|
+
// Add at least 25 examples for best results
|
|
198
|
+
],
|
|
199
|
+
test_goldens: [
|
|
200
|
+
{
|
|
201
|
+
fields: {
|
|
202
|
+
question: 'What is 3*3?',
|
|
203
|
+
context: 'Basic arithmetic',
|
|
204
|
+
},
|
|
205
|
+
answer: '9',
|
|
206
|
+
},
|
|
67
207
|
],
|
|
68
208
|
};
|
|
69
|
-
const response: NotDiamond.
|
|
209
|
+
const response: NotDiamond.PromptAdaptCreateResponse = await client.prompt.adapt.create(params);
|
|
210
|
+
console.log(response.adaptation_run_id);
|
|
70
211
|
```
|
|
71
212
|
|
|
72
213
|
Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors.
|
|
@@ -82,61 +223,56 @@ Request parameters that correspond to file uploads can be passed in many differe
|
|
|
82
223
|
|
|
83
224
|
```ts
|
|
84
225
|
import fs from 'fs';
|
|
85
|
-
import
|
|
226
|
+
import Notdiamond, { toFile } from 'notdiamond';
|
|
86
227
|
|
|
87
|
-
const client = new
|
|
228
|
+
const client = new Notdiamond();
|
|
88
229
|
|
|
89
230
|
// If you have access to Node `fs` we recommend using `fs.createReadStream()`:
|
|
90
|
-
await client.
|
|
91
|
-
constraint_priorities: 'constraint_priorities',
|
|
92
|
-
email: 'email',
|
|
93
|
-
llm_providers: 'llm_providers',
|
|
94
|
-
use_case_desc: 'use_case_desc',
|
|
95
|
-
user_id: 'user_id',
|
|
96
|
-
'x-token': 'x-token',
|
|
231
|
+
await client.customRouter.trainCustomRouter({
|
|
97
232
|
dataset_file: fs.createReadStream('/path/to/file'),
|
|
233
|
+
language: 'english',
|
|
234
|
+
llm_providers:
|
|
235
|
+
'[{"provider": "openai", "model": "gpt-4o"}, {"provider": "anthropic", "model": "claude-sonnet-4-5-20250929"}]',
|
|
236
|
+
maximize: true,
|
|
237
|
+
prompt_column: 'prompt',
|
|
98
238
|
});
|
|
99
239
|
|
|
100
240
|
// Or if you have the web `File` API you can pass a `File` instance:
|
|
101
|
-
await client.
|
|
102
|
-
constraint_priorities: 'constraint_priorities',
|
|
103
|
-
email: 'email',
|
|
104
|
-
llm_providers: 'llm_providers',
|
|
105
|
-
use_case_desc: 'use_case_desc',
|
|
106
|
-
user_id: 'user_id',
|
|
107
|
-
'x-token': 'x-token',
|
|
241
|
+
await client.customRouter.trainCustomRouter({
|
|
108
242
|
dataset_file: new File(['my bytes'], 'file'),
|
|
243
|
+
language: 'english',
|
|
244
|
+
llm_providers:
|
|
245
|
+
'[{"provider": "openai", "model": "gpt-4o"}, {"provider": "anthropic", "model": "claude-sonnet-4-5-20250929"}]',
|
|
246
|
+
maximize: true,
|
|
247
|
+
prompt_column: 'prompt',
|
|
109
248
|
});
|
|
110
249
|
|
|
111
250
|
// You can also pass a `fetch` `Response`:
|
|
112
|
-
await client.
|
|
113
|
-
constraint_priorities: 'constraint_priorities',
|
|
114
|
-
email: 'email',
|
|
115
|
-
llm_providers: 'llm_providers',
|
|
116
|
-
use_case_desc: 'use_case_desc',
|
|
117
|
-
user_id: 'user_id',
|
|
118
|
-
'x-token': 'x-token',
|
|
251
|
+
await client.customRouter.trainCustomRouter({
|
|
119
252
|
dataset_file: await fetch('https://somesite/file'),
|
|
253
|
+
language: 'english',
|
|
254
|
+
llm_providers:
|
|
255
|
+
'[{"provider": "openai", "model": "gpt-4o"}, {"provider": "anthropic", "model": "claude-sonnet-4-5-20250929"}]',
|
|
256
|
+
maximize: true,
|
|
257
|
+
prompt_column: 'prompt',
|
|
120
258
|
});
|
|
121
259
|
|
|
122
260
|
// Finally, if none of the above are convenient, you can use our `toFile` helper:
|
|
123
|
-
await client.
|
|
124
|
-
constraint_priorities: 'constraint_priorities',
|
|
125
|
-
email: 'email',
|
|
126
|
-
llm_providers: 'llm_providers',
|
|
127
|
-
use_case_desc: 'use_case_desc',
|
|
128
|
-
user_id: 'user_id',
|
|
129
|
-
'x-token': 'x-token',
|
|
261
|
+
await client.customRouter.trainCustomRouter({
|
|
130
262
|
dataset_file: await toFile(Buffer.from('my bytes'), 'file'),
|
|
263
|
+
language: 'english',
|
|
264
|
+
llm_providers:
|
|
265
|
+
'[{"provider": "openai", "model": "gpt-4o"}, {"provider": "anthropic", "model": "claude-sonnet-4-5-20250929"}]',
|
|
266
|
+
maximize: true,
|
|
267
|
+
prompt_column: 'prompt',
|
|
131
268
|
});
|
|
132
|
-
await client.
|
|
133
|
-
constraint_priorities: 'constraint_priorities',
|
|
134
|
-
email: 'email',
|
|
135
|
-
llm_providers: 'llm_providers',
|
|
136
|
-
use_case_desc: 'use_case_desc',
|
|
137
|
-
user_id: 'user_id',
|
|
138
|
-
'x-token': 'x-token',
|
|
269
|
+
await client.customRouter.trainCustomRouter({
|
|
139
270
|
dataset_file: await toFile(new Uint8Array([0, 1, 2]), 'file'),
|
|
271
|
+
language: 'english',
|
|
272
|
+
llm_providers:
|
|
273
|
+
'[{"provider": "openai", "model": "gpt-4o"}, {"provider": "anthropic", "model": "claude-sonnet-4-5-20250929"}]',
|
|
274
|
+
maximize: true,
|
|
275
|
+
prompt_column: 'prompt',
|
|
140
276
|
});
|
|
141
277
|
```
|
|
142
278
|
|
|
@@ -148,27 +284,47 @@ a subclass of `APIError` will be thrown:
|
|
|
148
284
|
|
|
149
285
|
<!-- prettier-ignore -->
|
|
150
286
|
```ts
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
287
|
+
import NotDiamond from 'notdiamond';
|
|
288
|
+
|
|
289
|
+
const client = new NotDiamond();
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
await client.prompt.adapt.create({
|
|
293
|
+
fields: ['question'],
|
|
294
|
+
system_prompt: 'You are a helpful assistant.',
|
|
295
|
+
target_models: [
|
|
296
|
+
{
|
|
297
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
298
|
+
provider: 'anthropic',
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
model: 'gemini-2.5-flash',
|
|
302
|
+
provider: 'google',
|
|
303
|
+
},
|
|
157
304
|
],
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
{
|
|
305
|
+
template: 'Question: {question}\nAnswer:',
|
|
306
|
+
train_goldens: [
|
|
307
|
+
{ fields: { question: 'What is 2+2?' }, answer: '4' },
|
|
308
|
+
// Add at least 25 examples...
|
|
309
|
+
],
|
|
310
|
+
test_goldens: [
|
|
311
|
+
{ fields: { question: 'What is 3*3?' }, answer: '9' },
|
|
161
312
|
],
|
|
162
|
-
})
|
|
163
|
-
.catch(async (err) => {
|
|
164
|
-
if (err instanceof NotDiamond.APIError) {
|
|
165
|
-
console.log(err.status); // 400
|
|
166
|
-
console.log(err.name); // BadRequestError
|
|
167
|
-
console.log(err.headers); // {server: 'nginx', ...}
|
|
168
|
-
} else {
|
|
169
|
-
throw err;
|
|
170
|
-
}
|
|
171
313
|
});
|
|
314
|
+
} catch (err) {
|
|
315
|
+
if (err instanceof NotDiamond.APIConnectionError) {
|
|
316
|
+
console.log('The server could not be reached');
|
|
317
|
+
console.log(err.cause); // an underlying Error, likely from fetch()
|
|
318
|
+
} else if (err instanceof NotDiamond.RateLimitError) {
|
|
319
|
+
console.log('A 429 status code was received; we should back off a bit.');
|
|
320
|
+
} else if (err instanceof NotDiamond.APIError) {
|
|
321
|
+
console.log(err.status); // 400
|
|
322
|
+
console.log(err.name); // BadRequestError
|
|
323
|
+
console.log(err.headers); // {server: 'nginx', ...}
|
|
324
|
+
} else {
|
|
325
|
+
throw err;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
172
328
|
```
|
|
173
329
|
|
|
174
330
|
Error codes are as follows:
|
|
@@ -195,12 +351,33 @@ You can use the `maxRetries` option to configure or disable this:
|
|
|
195
351
|
<!-- prettier-ignore -->
|
|
196
352
|
```js
|
|
197
353
|
// Configure the default for all requests:
|
|
198
|
-
const client = new
|
|
354
|
+
const client = new Notdiamond({
|
|
199
355
|
maxRetries: 0, // default is 2
|
|
200
356
|
});
|
|
201
357
|
|
|
202
358
|
// Or, configure per-request:
|
|
203
|
-
await client.
|
|
359
|
+
await client.prompt.adapt.create({
|
|
360
|
+
fields: ['question'],
|
|
361
|
+
system_prompt: 'You are a helpful assistant.',
|
|
362
|
+
target_models: [
|
|
363
|
+
{
|
|
364
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
365
|
+
provider: 'anthropic',
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
model: 'gemini-2.5-flash',
|
|
369
|
+
provider: 'google',
|
|
370
|
+
},
|
|
371
|
+
],
|
|
372
|
+
template: 'Question: {question}\nAnswer:',
|
|
373
|
+
train_goldens: [
|
|
374
|
+
{ fields: { question: 'What is 2+2?' }, answer: '4' },
|
|
375
|
+
// Add at least 25 examples...
|
|
376
|
+
],
|
|
377
|
+
test_goldens: [
|
|
378
|
+
{ fields: { question: 'What is 3*3?' }, answer: '9' },
|
|
379
|
+
],
|
|
380
|
+
}, {
|
|
204
381
|
maxRetries: 5,
|
|
205
382
|
});
|
|
206
383
|
```
|
|
@@ -212,13 +389,13 @@ Requests time out after 1 minute by default. You can configure this with a `time
|
|
|
212
389
|
<!-- prettier-ignore -->
|
|
213
390
|
```ts
|
|
214
391
|
// Configure the default for all requests:
|
|
215
|
-
const client = new
|
|
392
|
+
const client = new Notdiamond({
|
|
216
393
|
timeout: 20 * 1000, // 20 seconds (default is 1 minute)
|
|
217
394
|
});
|
|
218
395
|
|
|
219
|
-
// Override per-request:
|
|
220
|
-
await client.
|
|
221
|
-
timeout:
|
|
396
|
+
// Override per-request (note: prompt adaptation may take 10-30 minutes, so increase timeout accordingly):
|
|
397
|
+
await client.prompt.getAdaptStatus('your-adaptation-run-id', {
|
|
398
|
+
timeout: 120 * 1000, // 2 minutes
|
|
222
399
|
});
|
|
223
400
|
```
|
|
224
401
|
|
|
@@ -238,39 +415,61 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse
|
|
|
238
415
|
|
|
239
416
|
<!-- prettier-ignore -->
|
|
240
417
|
```ts
|
|
241
|
-
const client = new
|
|
242
|
-
|
|
243
|
-
const response = await client.
|
|
244
|
-
.
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
{
|
|
418
|
+
const client = new Notdiamond();
|
|
419
|
+
|
|
420
|
+
const response = await client.prompt.adapt
|
|
421
|
+
.create({
|
|
422
|
+
fields: ['question'],
|
|
423
|
+
system_prompt: 'You are a helpful assistant.',
|
|
424
|
+
target_models: [
|
|
425
|
+
{
|
|
426
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
427
|
+
provider: 'anthropic',
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
model: 'gemini-2.5-flash',
|
|
431
|
+
provider: 'google',
|
|
432
|
+
},
|
|
249
433
|
],
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
{
|
|
434
|
+
template: 'Question: {question}\nAnswer:',
|
|
435
|
+
train_goldens: [
|
|
436
|
+
{ fields: { question: 'What is 2+2?' }, answer: '4' },
|
|
437
|
+
// Add at least 25 examples...
|
|
438
|
+
],
|
|
439
|
+
test_goldens: [
|
|
440
|
+
{ fields: { question: 'What is 3*3?' }, answer: '9' },
|
|
253
441
|
],
|
|
254
442
|
})
|
|
255
443
|
.asResponse();
|
|
256
444
|
console.log(response.headers.get('X-My-Header'));
|
|
257
445
|
console.log(response.statusText); // access the underlying Response object
|
|
258
446
|
|
|
259
|
-
const { data:
|
|
260
|
-
.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
{
|
|
447
|
+
const { data: adaptResponse, response: raw } = await client.prompt.adapt
|
|
448
|
+
.create({
|
|
449
|
+
fields: ['question'],
|
|
450
|
+
system_prompt: 'You are a helpful assistant.',
|
|
451
|
+
target_models: [
|
|
452
|
+
{
|
|
453
|
+
model: 'claude-sonnet-4-5-20250929',
|
|
454
|
+
provider: 'anthropic',
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
model: 'gemini-2.5-flash',
|
|
458
|
+
provider: 'google',
|
|
459
|
+
},
|
|
460
|
+
],
|
|
461
|
+
template: 'Question: {question}\nAnswer:',
|
|
462
|
+
train_goldens: [
|
|
463
|
+
{ fields: { question: 'What is 2+2?' }, answer: '4' },
|
|
464
|
+
// Add at least 25 examples...
|
|
265
465
|
],
|
|
266
|
-
|
|
267
|
-
{
|
|
268
|
-
{ role: 'user', content: 'Explain quantum computing in simple terms' },
|
|
466
|
+
test_goldens: [
|
|
467
|
+
{ fields: { question: 'What is 3*3?' }, answer: '9' },
|
|
269
468
|
],
|
|
270
469
|
})
|
|
271
470
|
.withResponse();
|
|
272
471
|
console.log(raw.headers.get('X-My-Header'));
|
|
273
|
-
console.log(
|
|
472
|
+
console.log(adaptResponse.adaptation_run_id);
|
|
274
473
|
```
|
|
275
474
|
|
|
276
475
|
### Logging
|
|
@@ -283,13 +482,13 @@ console.log(response.providers);
|
|
|
283
482
|
|
|
284
483
|
The log level can be configured in two ways:
|
|
285
484
|
|
|
286
|
-
1. Via the `
|
|
485
|
+
1. Via the `NOTDIAMOND_LOG` environment variable
|
|
287
486
|
2. Using the `logLevel` client option (overrides the environment variable if set)
|
|
288
487
|
|
|
289
488
|
```ts
|
|
290
|
-
import
|
|
489
|
+
import Notdiamond from 'notdiamond';
|
|
291
490
|
|
|
292
|
-
const client = new
|
|
491
|
+
const client = new Notdiamond({
|
|
293
492
|
logLevel: 'debug', // Show all log messages
|
|
294
493
|
});
|
|
295
494
|
```
|
|
@@ -315,13 +514,13 @@ When providing a custom logger, the `logLevel` option still controls which messa
|
|
|
315
514
|
below the configured level will not be sent to your logger.
|
|
316
515
|
|
|
317
516
|
```ts
|
|
318
|
-
import
|
|
517
|
+
import Notdiamond from 'notdiamond';
|
|
319
518
|
import pino from 'pino';
|
|
320
519
|
|
|
321
520
|
const logger = pino();
|
|
322
521
|
|
|
323
|
-
const client = new
|
|
324
|
-
logger: logger.child({ name: '
|
|
522
|
+
const client = new Notdiamond({
|
|
523
|
+
logger: logger.child({ name: 'Notdiamond' }),
|
|
325
524
|
logLevel: 'debug', // Send all messages to pino, allowing it to filter
|
|
326
525
|
});
|
|
327
526
|
```
|
|
@@ -350,10 +549,14 @@ parameter. This library doesn't validate at runtime that the request matches the
|
|
|
350
549
|
send will be sent as-is.
|
|
351
550
|
|
|
352
551
|
```ts
|
|
353
|
-
client.
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
552
|
+
client.prompt.adapt.create({
|
|
553
|
+
fields: ['question'],
|
|
554
|
+
system_prompt: 'You are a helpful assistant.',
|
|
555
|
+
target_models: [{ model: 'claude-sonnet-4-5-20250929', provider: 'anthropic' }],
|
|
556
|
+
template: 'Question: {question}\nAnswer:',
|
|
557
|
+
train_goldens: [{ fields: { question: 'What is 2+2?' }, answer: '4' }],
|
|
558
|
+
// @ts-expect-error experimental_feature is not yet public
|
|
559
|
+
experimental_feature: true,
|
|
357
560
|
});
|
|
358
561
|
```
|
|
359
562
|
|
|
@@ -384,10 +587,10 @@ globalThis.fetch = fetch;
|
|
|
384
587
|
Or pass it to the client:
|
|
385
588
|
|
|
386
589
|
```ts
|
|
387
|
-
import
|
|
590
|
+
import Notdiamond from 'notdiamond';
|
|
388
591
|
import fetch from 'my-fetch';
|
|
389
592
|
|
|
390
|
-
const client = new
|
|
593
|
+
const client = new Notdiamond({ fetch });
|
|
391
594
|
```
|
|
392
595
|
|
|
393
596
|
### Fetch options
|
|
@@ -395,9 +598,9 @@ const client = new NotDiamond({ fetch });
|
|
|
395
598
|
If you want to set custom `fetch` options without overriding the `fetch` function, you can provide a `fetchOptions` object when instantiating the client or making a request. (Request-specific options override client options.)
|
|
396
599
|
|
|
397
600
|
```ts
|
|
398
|
-
import
|
|
601
|
+
import Notdiamond from 'notdiamond';
|
|
399
602
|
|
|
400
|
-
const client = new
|
|
603
|
+
const client = new Notdiamond({
|
|
401
604
|
fetchOptions: {
|
|
402
605
|
// `RequestInit` options
|
|
403
606
|
},
|
|
@@ -412,11 +615,11 @@ options to requests:
|
|
|
412
615
|
<img src="https://raw.githubusercontent.com/stainless-api/sdk-assets/refs/heads/main/node.svg" align="top" width="18" height="21"> **Node** <sup>[[docs](https://github.com/nodejs/undici/blob/main/docs/docs/api/ProxyAgent.md#example---proxyagent-with-fetch)]</sup>
|
|
413
616
|
|
|
414
617
|
```ts
|
|
415
|
-
import
|
|
618
|
+
import Notdiamond from 'notdiamond';
|
|
416
619
|
import * as undici from 'undici';
|
|
417
620
|
|
|
418
621
|
const proxyAgent = new undici.ProxyAgent('http://localhost:8888');
|
|
419
|
-
const client = new
|
|
622
|
+
const client = new Notdiamond({
|
|
420
623
|
fetchOptions: {
|
|
421
624
|
dispatcher: proxyAgent,
|
|
422
625
|
},
|
|
@@ -426,9 +629,9 @@ const client = new NotDiamond({
|
|
|
426
629
|
<img src="https://raw.githubusercontent.com/stainless-api/sdk-assets/refs/heads/main/bun.svg" align="top" width="18" height="21"> **Bun** <sup>[[docs](https://bun.sh/guides/http/proxy)]</sup>
|
|
427
630
|
|
|
428
631
|
```ts
|
|
429
|
-
import
|
|
632
|
+
import Notdiamond from 'notdiamond';
|
|
430
633
|
|
|
431
|
-
const client = new
|
|
634
|
+
const client = new Notdiamond({
|
|
432
635
|
fetchOptions: {
|
|
433
636
|
proxy: 'http://localhost:8888',
|
|
434
637
|
},
|
|
@@ -438,10 +641,10 @@ const client = new NotDiamond({
|
|
|
438
641
|
<img src="https://raw.githubusercontent.com/stainless-api/sdk-assets/refs/heads/main/deno.svg" align="top" width="18" height="21"> **Deno** <sup>[[docs](https://docs.deno.com/api/deno/~/Deno.createHttpClient)]</sup>
|
|
439
642
|
|
|
440
643
|
```ts
|
|
441
|
-
import
|
|
644
|
+
import Notdiamond from 'npm:notdiamond';
|
|
442
645
|
|
|
443
646
|
const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } });
|
|
444
|
-
const client = new
|
|
647
|
+
const client = new Notdiamond({
|
|
445
648
|
fetchOptions: {
|
|
446
649
|
client: httpClient,
|
|
447
650
|
},
|