notdiamond 2.0.0-rc1 → 2.0.0-rc10

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.
Files changed (137) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/README.md +299 -97
  3. package/client.d.mts +19 -33
  4. package/client.d.mts.map +1 -1
  5. package/client.d.ts +19 -33
  6. package/client.d.ts.map +1 -1
  7. package/client.js +19 -35
  8. package/client.js.map +1 -1
  9. package/client.mjs +19 -35
  10. package/client.mjs.map +1 -1
  11. package/internal/tslib.js +17 -17
  12. package/internal/utils/env.d.mts.map +1 -1
  13. package/internal/utils/env.d.ts.map +1 -1
  14. package/internal/utils/env.js +4 -2
  15. package/internal/utils/env.js.map +1 -1
  16. package/internal/utils/env.mjs +4 -2
  17. package/internal/utils/env.mjs.map +1 -1
  18. package/package.json +10 -11
  19. package/resources/custom-router.d.mts +145 -0
  20. package/resources/custom-router.d.mts.map +1 -0
  21. package/resources/custom-router.d.ts +145 -0
  22. package/resources/custom-router.d.ts.map +1 -0
  23. package/resources/custom-router.js +83 -0
  24. package/resources/custom-router.js.map +1 -0
  25. package/resources/custom-router.mjs +79 -0
  26. package/resources/custom-router.mjs.map +1 -0
  27. package/resources/index.d.mts +6 -6
  28. package/resources/index.d.mts.map +1 -1
  29. package/resources/index.d.ts +6 -6
  30. package/resources/index.d.ts.map +1 -1
  31. package/resources/index.js +6 -6
  32. package/resources/index.js.map +1 -1
  33. package/resources/index.mjs +3 -3
  34. package/resources/index.mjs.map +1 -1
  35. package/resources/model-router.d.mts +196 -0
  36. package/resources/model-router.d.mts.map +1 -0
  37. package/resources/model-router.d.ts +196 -0
  38. package/resources/model-router.d.ts.map +1 -0
  39. package/resources/model-router.js +70 -0
  40. package/resources/model-router.js.map +1 -0
  41. package/resources/model-router.mjs +66 -0
  42. package/resources/model-router.mjs.map +1 -0
  43. package/resources/models.d.mts +50 -25
  44. package/resources/models.d.mts.map +1 -1
  45. package/resources/models.d.ts +50 -25
  46. package/resources/models.d.ts.map +1 -1
  47. package/resources/models.js +5 -0
  48. package/resources/models.js.map +1 -1
  49. package/resources/models.mjs +5 -0
  50. package/resources/models.mjs.map +1 -1
  51. package/resources/preferences.d.mts +34 -48
  52. package/resources/preferences.d.mts.map +1 -1
  53. package/resources/preferences.d.ts +34 -48
  54. package/resources/preferences.d.ts.map +1 -1
  55. package/resources/preferences.js +14 -36
  56. package/resources/preferences.js.map +1 -1
  57. package/resources/preferences.mjs +14 -36
  58. package/resources/preferences.mjs.map +1 -1
  59. package/resources/prompt-adaptation.d.mts +339 -234
  60. package/resources/prompt-adaptation.d.mts.map +1 -1
  61. package/resources/prompt-adaptation.d.ts +339 -234
  62. package/resources/prompt-adaptation.d.ts.map +1 -1
  63. package/resources/prompt-adaptation.js +30 -53
  64. package/resources/prompt-adaptation.js.map +1 -1
  65. package/resources/prompt-adaptation.mjs +30 -53
  66. package/resources/prompt-adaptation.mjs.map +1 -1
  67. package/resources/report/index.d.mts +3 -0
  68. package/resources/report/index.d.mts.map +1 -0
  69. package/resources/report/index.d.ts +3 -0
  70. package/resources/report/index.d.ts.map +1 -0
  71. package/resources/report/index.js +9 -0
  72. package/resources/report/index.js.map +1 -0
  73. package/resources/report/index.mjs +4 -0
  74. package/resources/report/index.mjs.map +1 -0
  75. package/resources/report/metrics.d.mts +87 -0
  76. package/resources/report/metrics.d.mts.map +1 -0
  77. package/resources/report/metrics.d.ts +87 -0
  78. package/resources/report/metrics.d.ts.map +1 -0
  79. package/resources/report/metrics.js +57 -0
  80. package/resources/report/metrics.js.map +1 -0
  81. package/resources/report/metrics.mjs +53 -0
  82. package/resources/report/metrics.mjs.map +1 -0
  83. package/resources/report/report.d.mts +10 -0
  84. package/resources/report/report.d.mts.map +1 -0
  85. package/resources/report/report.d.ts +10 -0
  86. package/resources/report/report.d.ts.map +1 -0
  87. package/resources/report/report.js +17 -0
  88. package/resources/report/report.js.map +1 -0
  89. package/resources/report/report.mjs +12 -0
  90. package/resources/report/report.mjs.map +1 -0
  91. package/resources/report.d.mts +1 -244
  92. package/resources/report.d.mts.map +1 -1
  93. package/resources/report.d.ts +1 -244
  94. package/resources/report.d.ts.map +1 -1
  95. package/resources/report.js +2 -82
  96. package/resources/report.js.map +1 -1
  97. package/resources/report.mjs +1 -80
  98. package/resources/report.mjs.map +1 -1
  99. package/src/client.ts +65 -116
  100. package/src/internal/utils/env.ts +4 -2
  101. package/src/resources/custom-router.ts +168 -0
  102. package/src/resources/index.ts +23 -34
  103. package/src/resources/model-router.ts +224 -0
  104. package/src/resources/models.ts +55 -32
  105. package/src/resources/preferences.ts +40 -77
  106. package/src/resources/prompt-adaptation.ts +361 -291
  107. package/src/resources/report/index.ts +4 -0
  108. package/src/resources/report/metrics.ts +99 -0
  109. package/src/resources/report/report.ts +19 -0
  110. package/src/resources/report.ts +1 -298
  111. package/src/version.ts +1 -1
  112. package/version.d.mts +1 -1
  113. package/version.d.mts.map +1 -1
  114. package/version.d.ts +1 -1
  115. package/version.d.ts.map +1 -1
  116. package/version.js +1 -1
  117. package/version.js.map +1 -1
  118. package/version.mjs +1 -1
  119. package/version.mjs.map +1 -1
  120. package/resources/admin.d.mts +0 -4
  121. package/resources/admin.d.mts.map +0 -1
  122. package/resources/admin.d.ts +0 -4
  123. package/resources/admin.d.ts.map +0 -1
  124. package/resources/admin.js +0 -9
  125. package/resources/admin.js.map +0 -1
  126. package/resources/admin.mjs +0 -5
  127. package/resources/admin.mjs.map +0 -1
  128. package/resources/routing.d.mts +0 -391
  129. package/resources/routing.d.mts.map +0 -1
  130. package/resources/routing.d.ts +0 -391
  131. package/resources/routing.d.ts.map +0 -1
  132. package/resources/routing.js +0 -163
  133. package/resources/routing.js.map +0 -1
  134. package/resources/routing.mjs +0 -159
  135. package/resources/routing.mjs.map +0 -1
  136. package/src/resources/admin.ts +0 -5
  137. package/src/resources/routing.ts +0 -476
package/CHANGELOG.md CHANGED
@@ -1,5 +1,94 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.0-rc10 (2025-11-10)
4
+
5
+ Full Changelog: [v2.0.0-rc9...v2.0.0-rc10](https://github.com/Not-Diamond/not-diamond-typescript/compare/v2.0.0-rc9...v2.0.0-rc10)
6
+
7
+ ### Features
8
+
9
+ * **api:** manual updates ([b19bcb6](https://github.com/Not-Diamond/not-diamond-typescript/commit/b19bcb6965272f127345ef26b044fb74ac5a9f2a))
10
+
11
+ ## 2.0.0-rc9 (2025-11-10)
12
+
13
+ Full Changelog: [v2.0.0-rc9...v2.0.0-rc9](https://github.com/Not-Diamond/not-diamond-typescript/compare/v2.0.0-rc9...v2.0.0-rc9)
14
+
15
+ ### Features
16
+
17
+ * **api:** manual updates ([33b1872](https://github.com/Not-Diamond/not-diamond-typescript/commit/33b1872a28439049fe06472bdb7502ae9dd0d260))
18
+
19
+ ## 2.0.0-rc9 (2025-11-10)
20
+
21
+ Full Changelog: [v2.0.0-rc8...v2.0.0-rc9](https://github.com/Not-Diamond/not-diamond-typescript/compare/v2.0.0-rc8...v2.0.0-rc9)
22
+
23
+ ## 2.0.0-rc8 (2025-11-10)
24
+
25
+ Full Changelog: [v2.0.0-rc6...v2.0.0-rc8](https://github.com/Not-Diamond/not-diamond-typescript/compare/v2.0.0-rc6...v2.0.0-rc8)
26
+
27
+ ### Features
28
+
29
+ * **api:** manual updates ([46892a1](https://github.com/Not-Diamond/not-diamond-typescript/commit/46892a160ca21dedd68512bbc0f31dd26ab67586))
30
+
31
+ ## 2.0.0-rc6 (2025-11-07)
32
+
33
+ Full Changelog: [v2.0.0-rc5...v2.0.0-rc6](https://github.com/Not-Diamond/not-diamond-typescript/compare/v2.0.0-rc5...v2.0.0-rc6)
34
+
35
+ ### Features
36
+
37
+ * **api:** api update ([1d08dd1](https://github.com/Not-Diamond/not-diamond-typescript/commit/1d08dd1ee83a2f4f6147152c044858ad5c113247))
38
+
39
+ ## 2.0.0-rc5 (2025-11-06)
40
+
41
+ Full Changelog: [v2.0.0-rc4...v2.0.0-rc5](https://github.com/Not-Diamond/not-diamond-typescript/compare/v2.0.0-rc4...v2.0.0-rc5)
42
+
43
+ ### Features
44
+
45
+ * **api:** manual updates ([92ec1c6](https://github.com/Not-Diamond/not-diamond-typescript/commit/92ec1c69f2c5de881cdc36790aa84bcf568eae70))
46
+
47
+ ## 2.0.0-rc4 (2025-11-05)
48
+
49
+ Full Changelog: [v2.0.0-rc3...v2.0.0-rc4](https://github.com/Not-Diamond/not-diamond-typescript/compare/v2.0.0-rc3...v2.0.0-rc4)
50
+
51
+ ### Features
52
+
53
+ * **api:** manual updates ([dd4e78c](https://github.com/Not-Diamond/not-diamond-typescript/commit/dd4e78c59a3b8d07613b72e33cf0e414b62d7e30))
54
+
55
+
56
+ ### Chores
57
+
58
+ * update SDK settings ([42a98d0](https://github.com/Not-Diamond/not-diamond-typescript/commit/42a98d0699147509d025e232ad05ed97e6fa9ed3))
59
+
60
+ ## 2.0.0-rc3 (2025-11-05)
61
+
62
+ Full Changelog: [v2.0.0-rc2...v2.0.0-rc3](https://github.com/Not-Diamond/not-diamond-typescript/compare/v2.0.0-rc2...v2.0.0-rc3)
63
+
64
+ ### Features
65
+
66
+ * **api:** api update ([d087c64](https://github.com/Not-Diamond/not-diamond-typescript/commit/d087c6421949701acada35f89a1a8d009b581194))
67
+ * **api:** api update ([e431f34](https://github.com/Not-Diamond/not-diamond-typescript/commit/e431f343b558579f7940eacaef5d4f4b3656398f))
68
+ * **api:** api update ([8e6ad30](https://github.com/Not-Diamond/not-diamond-typescript/commit/8e6ad303485025b04622fcaf8d92686581fcc2a7))
69
+ * **api:** enable tests ([d94af20](https://github.com/Not-Diamond/not-diamond-typescript/commit/d94af20e2963644a0034fe1b60a7febf140b204f))
70
+ * **api:** manual updates ([20adad9](https://github.com/Not-Diamond/not-diamond-typescript/commit/20adad9ab8f778b3a8599c41cd91734b2c556614))
71
+ * **api:** regen docs ([ba39a05](https://github.com/Not-Diamond/not-diamond-typescript/commit/ba39a05f842dac7d5eb5153192ec08c3d87bf79f))
72
+ * **api:** verify mock tests enabled ([dcfbb6b](https://github.com/Not-Diamond/not-diamond-typescript/commit/dcfbb6b47900690ea531c510387b7e0392e23abb))
73
+
74
+
75
+ ### Bug Fixes
76
+
77
+ * **env:** handle empty environment variable values ([8360f59](https://github.com/Not-Diamond/not-diamond-typescript/commit/8360f59232e1887a1c6560a6195846c1c45f66e9))
78
+
79
+
80
+ ### Chores
81
+
82
+ * update SDK settings ([259c1ab](https://github.com/Not-Diamond/not-diamond-typescript/commit/259c1ab15d0c4d8bb1700ffa79fc24481ac4a4ae))
83
+
84
+ ## 2.0.0-rc2 (2025-10-31)
85
+
86
+ Full Changelog: [v2.0.0-rc1...v2.0.0-rc2](https://github.com/Not-Diamond/not-diamond-typescript/compare/v2.0.0-rc1...v2.0.0-rc2)
87
+
88
+ ### Features
89
+
90
+ * **api:** api update ([137fd6a](https://github.com/Not-Diamond/not-diamond-typescript/commit/137fd6ae915e6394e13e8d4416bf8d7441246606))
91
+
3
92
  ## 2.0.0-rc1 (2025-10-31)
4
93
 
5
94
  Full Changelog: [v0.3.0...v2.0.0-rc1](https://github.com/Not-Diamond/not-diamond-typescript/compare/v0.3.0...v2.0.0-rc1)
package/README.md CHANGED
@@ -4,10 +4,27 @@
4
4
 
5
5
  This library provides convenient access to the Not Diamond REST API from server-side TypeScript or JavaScript.
6
6
 
7
- 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).
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,126 @@ npm install notdiamond
16
33
 
17
34
  ## Usage
18
35
 
19
- The full API of this library can be found in [api.md](api.md).
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
- ```js
43
+ ```ts
23
44
  import NotDiamond from 'notdiamond';
24
45
 
25
46
  const client = new NotDiamond({
26
47
  apiKey: process.env['NOT_DIAMOND_API_KEY'], // This is the default and can be omitted
27
- environment: 'staging', // defaults to 'production'
28
48
  });
29
49
 
30
- const response = await client.routing.selectModel({
50
+ // Step 1: Start a prompt adaptation job
51
+ const adaptation = await client.prompt.adapt.create({
52
+ fields: ['question'],
53
+ system_prompt: 'You are a helpful assistant that answers questions accurately.',
54
+ target_models: [
55
+ {
56
+ model: 'claude-sonnet-4-5-20250929',
57
+ provider: 'anthropic',
58
+ },
59
+ {
60
+ model: 'gemini-2.5-flash',
61
+ provider: 'google',
62
+ },
63
+ ],
64
+ template: 'Question: {question}\nAnswer:',
65
+ train_goldens: [
66
+ { fields: { question: 'What is 2+2?' }, answer: '4' },
67
+ { fields: { question: 'What is the capital of France?' }, answer: 'Paris' },
68
+ { fields: { question: 'Who wrote Romeo and Juliet?' }, answer: 'William Shakespeare' },
69
+ // Add at least 25 training examples for best results
70
+ // More examples = better adaptation quality
71
+ ],
72
+ test_goldens: [
73
+ { fields: { question: 'What is 3*3?' }, answer: '9' },
74
+ { fields: { question: 'What is the largest ocean?' }, answer: 'Pacific Ocean' },
75
+ // Add test examples to validate performance
76
+ ],
77
+ evaluation_metric: 'LLMaaJ:Sem_Sim_1', // Or use custom evaluation
78
+ });
79
+
80
+ console.log(`Adaptation started: ${adaptation.adaptation_run_id}`);
81
+
82
+ // Step 2: Poll for completion (typically takes 10-30 minutes)
83
+ let status;
84
+ while (true) {
85
+ status = await client.prompt.getAdaptStatus(adaptation.adaptation_run_id);
86
+ console.log(`Status: ${status.status}`);
87
+
88
+ if (status.status === 'queued') {
89
+ console.log(`Queue position: ${status.queue_position}`);
90
+ }
91
+
92
+ if (status.status === 'completed' || status.status === 'failed') {
93
+ break;
94
+ }
95
+
96
+ await new Promise(resolve => setTimeout(resolve, 30000)); // Poll every 30 seconds
97
+ }
98
+
99
+ // Step 3: Get the optimized prompts
100
+ if (status.status === 'completed') {
101
+ const results = await client.prompt.getAdaptResults(adaptation.adaptation_run_id);
102
+
103
+ console.log(`\nOrigin model baseline: ${results.origin_model.score.toFixed(2)}`);
104
+
105
+ for (const target of results.target_models) {
106
+ console.log('\n' + '='.repeat(50));
107
+ console.log(`Model: ${target.model.model} (${target.model.provider})`);
108
+ console.log(`Optimized System Prompt:\n${target.system_prompt}`);
109
+ console.log(`Optimized Template:\n${target.user_message_template}`);
110
+ console.log(`Pre-optimization score: ${target.pre_optimization_score.toFixed(2)}`);
111
+ console.log(`Post-optimization score: ${target.post_optimization_score.toFixed(2)}`);
112
+ console.log(`Improvement: ${((target.post_optimization_score / target.pre_optimization_score - 1) * 100).toFixed(1)}%`);
113
+ console.log(`Cost: $${target.cost.toFixed(4)}`);
114
+ }
115
+ }
116
+ ```
117
+
118
+ #### Key Features
119
+
120
+ - **Automatic Optimization**: Adapts both system prompts and user message templates
121
+ - **Evaluation Metrics**: Choose from standard metrics (semantic similarity, JSON matching, SQL) or provide custom evaluation
122
+ - **Dataset Requirements**: Minimum 25 training examples (more examples = better results)
123
+ - **Processing Time**: Typically 10-30 minutes depending on dataset size and number of target models
124
+ - **Subscription Tiers**: Support for 1-10 target models depending on your plan
125
+
126
+ #### Evaluation Metrics
127
+
128
+ Choose from standard metrics:
129
+
130
+ - `LLMaaJ:Sem_Sim_1`, `LLMaaJ:Sem_Sim_3`, `LLMaaJ:Sem_Sim_10` - Semantic similarity
131
+ - `LLMaaJ:SQL` - SQL query validation
132
+ - `JSON_Match` - JSON structure matching
133
+
134
+ Or provide custom evaluation configuration with your own LLM judge.
135
+
136
+ #### Best Practices
137
+
138
+ 1. **Use Representative Examples**: Include diverse examples from your production workload
139
+ 2. **Sufficient Dataset Size**: Use at least 25 training examples (50+ recommended)
140
+ 3. **Train/Test Split**: Separate train_goldens and test_goldens for proper validation
141
+ 4. **A/B Test Results**: Validate optimized prompts in production before full deployment
142
+
143
+ For more details, see the [Prompt Adaptation documentation](https://docs.notdiamond.ai/docs/adapting-prompts-to-new-models).
144
+
145
+ ### Model Routing
146
+
147
+ Not Diamond also provides intelligent model routing to select the best model for your query:
148
+
149
+ <!-- prettier-ignore -->
150
+ ```ts
151
+ const response = await client.modelRouter.selectModel({
31
152
  llm_providers: [
32
153
  { model: 'gpt-4o', provider: 'openai' },
33
- { model: 'claude-3-5-sonnet-20241022', provider: 'anthropic' },
34
- { model: 'gemini-1.5-pro', provider: 'google' },
154
+ { model: 'claude-sonnet-4-5-20250929', provider: 'anthropic' },
155
+ { model: 'gemini-2.5-flash', provider: 'google' },
35
156
  ],
36
157
  messages: [
37
158
  { role: 'system', content: 'You are a helpful assistant.' },
@@ -52,21 +173,40 @@ import NotDiamond from 'notdiamond';
52
173
 
53
174
  const client = new NotDiamond({
54
175
  apiKey: process.env['NOT_DIAMOND_API_KEY'], // This is the default and can be omitted
55
- environment: 'staging', // defaults to 'production'
56
176
  });
57
177
 
58
- const params: NotDiamond.RoutingSelectModelParams = {
59
- llm_providers: [
60
- { model: 'gpt-4o', provider: 'openai' },
61
- { model: 'claude-3-5-sonnet-20241022', provider: 'anthropic' },
62
- { model: 'gemini-1.5-pro', provider: 'google' },
178
+ const params: NotDiamond.PromptAdaptCreateParams = {
179
+ fields: ['question', 'context'],
180
+ system_prompt: 'You are a helpful assistant.',
181
+ target_models: [
182
+ {
183
+ model: 'claude-sonnet-4-5-20250929',
184
+ provider: 'anthropic',
185
+ },
63
186
  ],
64
- messages: [
65
- { role: 'system', content: 'You are a helpful assistant.' },
66
- { role: 'user', content: 'Explain quantum computing in simple terms' },
187
+ template: 'Context: {context}\nQuestion: {question}\nAnswer:',
188
+ train_goldens: [
189
+ {
190
+ fields: {
191
+ question: 'What is 2+2?',
192
+ context: 'Basic arithmetic',
193
+ },
194
+ answer: '4',
195
+ },
196
+ // Add at least 25 examples for best results
197
+ ],
198
+ test_goldens: [
199
+ {
200
+ fields: {
201
+ question: 'What is 3*3?',
202
+ context: 'Basic arithmetic',
203
+ },
204
+ answer: '9',
205
+ },
67
206
  ],
68
207
  };
69
- const response: NotDiamond.RoutingSelectModelResponse = await client.routing.selectModel(params);
208
+ const response: NotDiamond.PromptAdaptCreateResponse = await client.prompt.adapt.create(params);
209
+ console.log(response.adaptation_run_id);
70
210
  ```
71
211
 
72
212
  Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors.
@@ -87,56 +227,51 @@ import NotDiamond, { toFile } from 'notdiamond';
87
227
  const client = new NotDiamond();
88
228
 
89
229
  // If you have access to Node `fs` we recommend using `fs.createReadStream()`:
90
- await client.routing.createSurveyResponse({
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',
230
+ await client.customRouter.trainCustomRouter({
97
231
  dataset_file: fs.createReadStream('/path/to/file'),
232
+ language: 'english',
233
+ llm_providers:
234
+ '[{"provider": "openai", "model": "gpt-4o"}, {"provider": "anthropic", "model": "claude-sonnet-4-5-20250929"}]',
235
+ maximize: true,
236
+ prompt_column: 'prompt',
98
237
  });
99
238
 
100
239
  // Or if you have the web `File` API you can pass a `File` instance:
101
- await client.routing.createSurveyResponse({
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',
240
+ await client.customRouter.trainCustomRouter({
108
241
  dataset_file: new File(['my bytes'], 'file'),
242
+ language: 'english',
243
+ llm_providers:
244
+ '[{"provider": "openai", "model": "gpt-4o"}, {"provider": "anthropic", "model": "claude-sonnet-4-5-20250929"}]',
245
+ maximize: true,
246
+ prompt_column: 'prompt',
109
247
  });
110
248
 
111
249
  // You can also pass a `fetch` `Response`:
112
- await client.routing.createSurveyResponse({
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',
250
+ await client.customRouter.trainCustomRouter({
119
251
  dataset_file: await fetch('https://somesite/file'),
252
+ language: 'english',
253
+ llm_providers:
254
+ '[{"provider": "openai", "model": "gpt-4o"}, {"provider": "anthropic", "model": "claude-sonnet-4-5-20250929"}]',
255
+ maximize: true,
256
+ prompt_column: 'prompt',
120
257
  });
121
258
 
122
259
  // Finally, if none of the above are convenient, you can use our `toFile` helper:
123
- await client.routing.createSurveyResponse({
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',
260
+ await client.customRouter.trainCustomRouter({
130
261
  dataset_file: await toFile(Buffer.from('my bytes'), 'file'),
262
+ language: 'english',
263
+ llm_providers:
264
+ '[{"provider": "openai", "model": "gpt-4o"}, {"provider": "anthropic", "model": "claude-sonnet-4-5-20250929"}]',
265
+ maximize: true,
266
+ prompt_column: 'prompt',
131
267
  });
132
- await client.routing.createSurveyResponse({
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',
268
+ await client.customRouter.trainCustomRouter({
139
269
  dataset_file: await toFile(new Uint8Array([0, 1, 2]), 'file'),
270
+ language: 'english',
271
+ llm_providers:
272
+ '[{"provider": "openai", "model": "gpt-4o"}, {"provider": "anthropic", "model": "claude-sonnet-4-5-20250929"}]',
273
+ maximize: true,
274
+ prompt_column: 'prompt',
140
275
  });
141
276
  ```
142
277
 
@@ -148,27 +283,47 @@ a subclass of `APIError` will be thrown:
148
283
 
149
284
  <!-- prettier-ignore -->
150
285
  ```ts
151
- const response = await client.routing
152
- .selectModel({
153
- llm_providers: [
154
- { model: 'gpt-4o', provider: 'openai' },
155
- { model: 'claude-3-5-sonnet-20241022', provider: 'anthropic' },
156
- { model: 'gemini-1.5-pro', provider: 'google' },
286
+ import NotDiamond from 'notdiamond';
287
+
288
+ const client = new NotDiamond();
289
+
290
+ try {
291
+ await client.prompt.adapt.create({
292
+ fields: ['question'],
293
+ system_prompt: 'You are a helpful assistant.',
294
+ target_models: [
295
+ {
296
+ model: 'claude-sonnet-4-5-20250929',
297
+ provider: 'anthropic',
298
+ },
299
+ {
300
+ model: 'gemini-2.5-flash',
301
+ provider: 'google',
302
+ },
157
303
  ],
158
- messages: [
159
- { role: 'system', content: 'You are a helpful assistant.' },
160
- { role: 'user', content: 'Explain quantum computing in simple terms' },
304
+ template: 'Question: {question}\nAnswer:',
305
+ train_goldens: [
306
+ { fields: { question: 'What is 2+2?' }, answer: '4' },
307
+ // Add at least 25 examples...
308
+ ],
309
+ test_goldens: [
310
+ { fields: { question: 'What is 3*3?' }, answer: '9' },
161
311
  ],
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
312
  });
313
+ } catch (err) {
314
+ if (err instanceof NotDiamond.APIConnectionError) {
315
+ console.log('The server could not be reached');
316
+ console.log(err.cause); // an underlying Error, likely from fetch()
317
+ } else if (err instanceof NotDiamond.RateLimitError) {
318
+ console.log('A 429 status code was received; we should back off a bit.');
319
+ } else if (err instanceof NotDiamond.APIError) {
320
+ console.log(err.status); // 400
321
+ console.log(err.name); // BadRequestError
322
+ console.log(err.headers); // {server: 'nginx', ...}
323
+ } else {
324
+ throw err;
325
+ }
326
+ }
172
327
  ```
173
328
 
174
329
  Error codes are as follows:
@@ -200,7 +355,28 @@ const client = new NotDiamond({
200
355
  });
201
356
 
202
357
  // Or, configure per-request:
203
- await client.routing.selectModel({ llm_providers: [{ model: 'gpt-4o', provider: 'openai' }, { model: 'claude-3-5-sonnet-20241022', provider: 'anthropic' }, { model: 'gemini-1.5-pro', provider: 'google' }], messages: [{ role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: 'Explain quantum computing in simple terms' }] }, {
358
+ await client.prompt.adapt.create({
359
+ fields: ['question'],
360
+ system_prompt: 'You are a helpful assistant.',
361
+ target_models: [
362
+ {
363
+ model: 'claude-sonnet-4-5-20250929',
364
+ provider: 'anthropic',
365
+ },
366
+ {
367
+ model: 'gemini-2.5-flash',
368
+ provider: 'google',
369
+ },
370
+ ],
371
+ template: 'Question: {question}\nAnswer:',
372
+ train_goldens: [
373
+ { fields: { question: 'What is 2+2?' }, answer: '4' },
374
+ // Add at least 25 examples...
375
+ ],
376
+ test_goldens: [
377
+ { fields: { question: 'What is 3*3?' }, answer: '9' },
378
+ ],
379
+ }, {
204
380
  maxRetries: 5,
205
381
  });
206
382
  ```
@@ -216,9 +392,9 @@ const client = new NotDiamond({
216
392
  timeout: 20 * 1000, // 20 seconds (default is 1 minute)
217
393
  });
218
394
 
219
- // Override per-request:
220
- await client.routing.selectModel({ llm_providers: [{ model: 'gpt-4o', provider: 'openai' }, { model: 'claude-3-5-sonnet-20241022', provider: 'anthropic' }, { model: 'gemini-1.5-pro', provider: 'google' }], messages: [{ role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: 'Explain quantum computing in simple terms' }] }, {
221
- timeout: 5 * 1000,
395
+ // Override per-request (note: prompt adaptation may take 10-30 minutes, so increase timeout accordingly):
396
+ await client.prompt.getAdaptStatus('your-adaptation-run-id', {
397
+ timeout: 120 * 1000, // 2 minutes
222
398
  });
223
399
  ```
224
400
 
@@ -240,37 +416,59 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse
240
416
  ```ts
241
417
  const client = new NotDiamond();
242
418
 
243
- const response = await client.routing
244
- .selectModel({
245
- llm_providers: [
246
- { model: 'gpt-4o', provider: 'openai' },
247
- { model: 'claude-3-5-sonnet-20241022', provider: 'anthropic' },
248
- { model: 'gemini-1.5-pro', provider: 'google' },
419
+ const response = await client.prompt.adapt
420
+ .create({
421
+ fields: ['question'],
422
+ system_prompt: 'You are a helpful assistant.',
423
+ target_models: [
424
+ {
425
+ model: 'claude-sonnet-4-5-20250929',
426
+ provider: 'anthropic',
427
+ },
428
+ {
429
+ model: 'gemini-2.5-flash',
430
+ provider: 'google',
431
+ },
249
432
  ],
250
- messages: [
251
- { role: 'system', content: 'You are a helpful assistant.' },
252
- { role: 'user', content: 'Explain quantum computing in simple terms' },
433
+ template: 'Question: {question}\nAnswer:',
434
+ train_goldens: [
435
+ { fields: { question: 'What is 2+2?' }, answer: '4' },
436
+ // Add at least 25 examples...
437
+ ],
438
+ test_goldens: [
439
+ { fields: { question: 'What is 3*3?' }, answer: '9' },
253
440
  ],
254
441
  })
255
442
  .asResponse();
256
443
  console.log(response.headers.get('X-My-Header'));
257
444
  console.log(response.statusText); // access the underlying Response object
258
445
 
259
- const { data: response, response: raw } = await client.routing
260
- .selectModel({
261
- llm_providers: [
262
- { model: 'gpt-4o', provider: 'openai' },
263
- { model: 'claude-3-5-sonnet-20241022', provider: 'anthropic' },
264
- { model: 'gemini-1.5-pro', provider: 'google' },
446
+ const { data: adaptResponse, response: raw } = await client.prompt.adapt
447
+ .create({
448
+ fields: ['question'],
449
+ system_prompt: 'You are a helpful assistant.',
450
+ target_models: [
451
+ {
452
+ model: 'claude-sonnet-4-5-20250929',
453
+ provider: 'anthropic',
454
+ },
455
+ {
456
+ model: 'gemini-2.5-flash',
457
+ provider: 'google',
458
+ },
459
+ ],
460
+ template: 'Question: {question}\nAnswer:',
461
+ train_goldens: [
462
+ { fields: { question: 'What is 2+2?' }, answer: '4' },
463
+ // Add at least 25 examples...
265
464
  ],
266
- messages: [
267
- { role: 'system', content: 'You are a helpful assistant.' },
268
- { role: 'user', content: 'Explain quantum computing in simple terms' },
465
+ test_goldens: [
466
+ { fields: { question: 'What is 3*3?' }, answer: '9' },
269
467
  ],
270
468
  })
271
469
  .withResponse();
272
470
  console.log(raw.headers.get('X-My-Header'));
273
- console.log(response.providers);
471
+ console.log(adaptResponse.adaptation_run_id);
274
472
  ```
275
473
 
276
474
  ### Logging
@@ -350,10 +548,14 @@ parameter. This library doesn't validate at runtime that the request matches the
350
548
  send will be sent as-is.
351
549
 
352
550
  ```ts
353
- client.routing.selectModel({
354
- // ...
355
- // @ts-expect-error baz is not yet public
356
- baz: 'undocumented option',
551
+ client.prompt.adapt.create({
552
+ fields: ['question'],
553
+ system_prompt: 'You are a helpful assistant.',
554
+ target_models: [{ model: 'claude-sonnet-4-5-20250929', provider: 'anthropic' }],
555
+ template: 'Question: {question}\nAnswer:',
556
+ train_goldens: [{ fields: { question: 'What is 2+2?' }, answer: '4' }],
557
+ // @ts-expect-error experimental_feature is not yet public
558
+ experimental_feature: true,
357
559
  });
358
560
  ```
359
561