together 1.2.11__py3-none-any.whl → 2.0.0a8__py3-none-any.whl

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 (201) hide show
  1. together/__init__.py +101 -63
  2. together/_base_client.py +1995 -0
  3. together/_client.py +1033 -0
  4. together/_compat.py +219 -0
  5. together/_constants.py +14 -0
  6. together/_exceptions.py +108 -0
  7. together/_files.py +123 -0
  8. together/_models.py +857 -0
  9. together/_qs.py +150 -0
  10. together/_resource.py +43 -0
  11. together/_response.py +830 -0
  12. together/_streaming.py +370 -0
  13. together/_types.py +260 -0
  14. together/_utils/__init__.py +64 -0
  15. together/_utils/_compat.py +45 -0
  16. together/_utils/_datetime_parse.py +136 -0
  17. together/_utils/_logs.py +25 -0
  18. together/_utils/_proxy.py +65 -0
  19. together/_utils/_reflection.py +42 -0
  20. together/_utils/_resources_proxy.py +24 -0
  21. together/_utils/_streams.py +12 -0
  22. together/_utils/_sync.py +58 -0
  23. together/_utils/_transform.py +457 -0
  24. together/_utils/_typing.py +156 -0
  25. together/_utils/_utils.py +421 -0
  26. together/_version.py +4 -0
  27. together/lib/.keep +4 -0
  28. together/lib/__init__.py +23 -0
  29. together/lib/cli/api/endpoints.py +467 -0
  30. together/lib/cli/api/evals.py +588 -0
  31. together/{cli → lib/cli}/api/files.py +20 -17
  32. together/lib/cli/api/fine_tuning.py +566 -0
  33. together/lib/cli/api/models.py +140 -0
  34. together/lib/cli/api/utils.py +50 -0
  35. together/{cli → lib/cli}/cli.py +17 -23
  36. together/lib/constants.py +61 -0
  37. together/lib/resources/__init__.py +11 -0
  38. together/lib/resources/files.py +999 -0
  39. together/lib/resources/fine_tuning.py +280 -0
  40. together/lib/resources/models.py +35 -0
  41. together/lib/types/__init__.py +13 -0
  42. together/lib/types/error.py +9 -0
  43. together/lib/types/fine_tuning.py +455 -0
  44. together/{utils → lib/utils}/__init__.py +7 -10
  45. together/{utils → lib/utils}/_log.py +18 -13
  46. together/lib/utils/files.py +628 -0
  47. together/lib/utils/serializer.py +10 -0
  48. together/{utils → lib/utils}/tools.py +17 -2
  49. together/resources/__init__.py +225 -24
  50. together/resources/audio/__init__.py +75 -0
  51. together/resources/audio/audio.py +198 -0
  52. together/resources/audio/speech.py +605 -0
  53. together/resources/audio/transcriptions.py +282 -0
  54. together/resources/audio/translations.py +256 -0
  55. together/resources/audio/voices.py +135 -0
  56. together/resources/batches.py +417 -0
  57. together/resources/chat/__init__.py +30 -21
  58. together/resources/chat/chat.py +102 -0
  59. together/resources/chat/completions.py +1063 -257
  60. together/resources/code_interpreter/__init__.py +33 -0
  61. together/resources/code_interpreter/code_interpreter.py +258 -0
  62. together/resources/code_interpreter/sessions.py +135 -0
  63. together/resources/completions.py +890 -225
  64. together/resources/embeddings.py +172 -68
  65. together/resources/endpoints.py +711 -0
  66. together/resources/evals.py +452 -0
  67. together/resources/files.py +397 -120
  68. together/resources/fine_tuning.py +1033 -0
  69. together/resources/hardware.py +181 -0
  70. together/resources/images.py +256 -108
  71. together/resources/jobs.py +214 -0
  72. together/resources/models.py +251 -44
  73. together/resources/rerank.py +190 -92
  74. together/resources/videos.py +374 -0
  75. together/types/__init__.py +66 -73
  76. together/types/audio/__init__.py +10 -0
  77. together/types/audio/speech_create_params.py +75 -0
  78. together/types/audio/transcription_create_params.py +54 -0
  79. together/types/audio/transcription_create_response.py +111 -0
  80. together/types/audio/translation_create_params.py +40 -0
  81. together/types/audio/translation_create_response.py +70 -0
  82. together/types/audio/voice_list_response.py +23 -0
  83. together/types/audio_speech_stream_chunk.py +16 -0
  84. together/types/autoscaling.py +13 -0
  85. together/types/autoscaling_param.py +15 -0
  86. together/types/batch_create_params.py +24 -0
  87. together/types/batch_create_response.py +14 -0
  88. together/types/batch_job.py +45 -0
  89. together/types/batch_list_response.py +10 -0
  90. together/types/chat/__init__.py +18 -0
  91. together/types/chat/chat_completion.py +60 -0
  92. together/types/chat/chat_completion_chunk.py +61 -0
  93. together/types/chat/chat_completion_structured_message_image_url_param.py +18 -0
  94. together/types/chat/chat_completion_structured_message_text_param.py +13 -0
  95. together/types/chat/chat_completion_structured_message_video_url_param.py +18 -0
  96. together/types/chat/chat_completion_usage.py +13 -0
  97. together/types/chat/chat_completion_warning.py +9 -0
  98. together/types/chat/completion_create_params.py +329 -0
  99. together/types/code_interpreter/__init__.py +5 -0
  100. together/types/code_interpreter/session_list_response.py +31 -0
  101. together/types/code_interpreter_execute_params.py +45 -0
  102. together/types/completion.py +42 -0
  103. together/types/completion_chunk.py +66 -0
  104. together/types/completion_create_params.py +138 -0
  105. together/types/dedicated_endpoint.py +44 -0
  106. together/types/embedding.py +24 -0
  107. together/types/embedding_create_params.py +31 -0
  108. together/types/endpoint_create_params.py +43 -0
  109. together/types/endpoint_list_avzones_response.py +11 -0
  110. together/types/endpoint_list_params.py +18 -0
  111. together/types/endpoint_list_response.py +41 -0
  112. together/types/endpoint_update_params.py +27 -0
  113. together/types/eval_create_params.py +263 -0
  114. together/types/eval_create_response.py +16 -0
  115. together/types/eval_list_params.py +21 -0
  116. together/types/eval_list_response.py +10 -0
  117. together/types/eval_status_response.py +100 -0
  118. together/types/evaluation_job.py +139 -0
  119. together/types/execute_response.py +108 -0
  120. together/types/file_delete_response.py +13 -0
  121. together/types/file_list.py +12 -0
  122. together/types/file_purpose.py +9 -0
  123. together/types/file_response.py +31 -0
  124. together/types/file_type.py +7 -0
  125. together/types/fine_tuning_cancel_response.py +194 -0
  126. together/types/fine_tuning_content_params.py +24 -0
  127. together/types/fine_tuning_delete_params.py +11 -0
  128. together/types/fine_tuning_delete_response.py +12 -0
  129. together/types/fine_tuning_list_checkpoints_response.py +21 -0
  130. together/types/fine_tuning_list_events_response.py +12 -0
  131. together/types/fine_tuning_list_response.py +199 -0
  132. together/types/finetune_event.py +41 -0
  133. together/types/finetune_event_type.py +33 -0
  134. together/types/finetune_response.py +177 -0
  135. together/types/hardware_list_params.py +16 -0
  136. together/types/hardware_list_response.py +58 -0
  137. together/types/image_data_b64.py +15 -0
  138. together/types/image_data_url.py +15 -0
  139. together/types/image_file.py +23 -0
  140. together/types/image_generate_params.py +85 -0
  141. together/types/job_list_response.py +47 -0
  142. together/types/job_retrieve_response.py +43 -0
  143. together/types/log_probs.py +18 -0
  144. together/types/model_list_response.py +10 -0
  145. together/types/model_object.py +42 -0
  146. together/types/model_upload_params.py +36 -0
  147. together/types/model_upload_response.py +23 -0
  148. together/types/rerank_create_params.py +36 -0
  149. together/types/rerank_create_response.py +36 -0
  150. together/types/tool_choice.py +23 -0
  151. together/types/tool_choice_param.py +23 -0
  152. together/types/tools_param.py +23 -0
  153. together/types/training_method_dpo.py +22 -0
  154. together/types/training_method_sft.py +18 -0
  155. together/types/video_create_params.py +86 -0
  156. together/types/video_job.py +57 -0
  157. together-2.0.0a8.dist-info/METADATA +680 -0
  158. together-2.0.0a8.dist-info/RECORD +164 -0
  159. {together-1.2.11.dist-info → together-2.0.0a8.dist-info}/WHEEL +1 -1
  160. together-2.0.0a8.dist-info/entry_points.txt +2 -0
  161. {together-1.2.11.dist-info → together-2.0.0a8.dist-info/licenses}/LICENSE +1 -1
  162. together/abstract/api_requestor.py +0 -723
  163. together/cli/api/chat.py +0 -276
  164. together/cli/api/completions.py +0 -119
  165. together/cli/api/finetune.py +0 -272
  166. together/cli/api/images.py +0 -82
  167. together/cli/api/models.py +0 -42
  168. together/client.py +0 -157
  169. together/constants.py +0 -31
  170. together/error.py +0 -191
  171. together/filemanager.py +0 -388
  172. together/legacy/__init__.py +0 -0
  173. together/legacy/base.py +0 -27
  174. together/legacy/complete.py +0 -93
  175. together/legacy/embeddings.py +0 -27
  176. together/legacy/files.py +0 -146
  177. together/legacy/finetune.py +0 -177
  178. together/legacy/images.py +0 -27
  179. together/legacy/models.py +0 -44
  180. together/resources/finetune.py +0 -489
  181. together/together_response.py +0 -50
  182. together/types/abstract.py +0 -26
  183. together/types/chat_completions.py +0 -171
  184. together/types/common.py +0 -65
  185. together/types/completions.py +0 -104
  186. together/types/embeddings.py +0 -35
  187. together/types/error.py +0 -16
  188. together/types/files.py +0 -89
  189. together/types/finetune.py +0 -265
  190. together/types/images.py +0 -42
  191. together/types/models.py +0 -44
  192. together/types/rerank.py +0 -43
  193. together/utils/api_helpers.py +0 -84
  194. together/utils/files.py +0 -204
  195. together/version.py +0 -6
  196. together-1.2.11.dist-info/METADATA +0 -408
  197. together-1.2.11.dist-info/RECORD +0 -58
  198. together-1.2.11.dist-info/entry_points.txt +0 -3
  199. /together/{abstract → lib/cli}/__init__.py +0 -0
  200. /together/{cli → lib/cli/api}/__init__.py +0 -0
  201. /together/{cli/api/__init__.py → py.typed} +0 -0
@@ -0,0 +1,588 @@
1
+ import sys
2
+ import json
3
+ from typing import Any, Dict, List, Union, Literal, TypeVar, Callable, Optional, cast
4
+ from functools import wraps
5
+
6
+ import click
7
+ from tabulate import tabulate
8
+
9
+ from together import APIError, Together, TogetherError
10
+ from together._types import omit
11
+ from together.lib.utils.serializer import datetime_serializer
12
+ from together.types.eval_create_params import (
13
+ ParametersEvaluationScoreParameters,
14
+ ParametersEvaluationCompareParameters,
15
+ ParametersEvaluationClassifyParameters,
16
+ ParametersEvaluationScoreParametersJudge,
17
+ ParametersEvaluationCompareParametersJudge,
18
+ ParametersEvaluationClassifyParametersJudge,
19
+ ParametersEvaluationScoreParametersModelToEvaluate,
20
+ ParametersEvaluationClassifyParametersModelToEvaluate,
21
+ ParametersEvaluationCompareParametersModelAEvaluationModelRequest,
22
+ ParametersEvaluationCompareParametersModelBEvaluationModelRequest,
23
+ )
24
+
25
+
26
+ def print_api_error(e: Union[APIError, TogetherError]) -> None:
27
+ if isinstance(e, APIError):
28
+ error_details = cast(Dict[str, Any], e.body)["error"]["message"]
29
+
30
+ if error_details and ("credentials" in error_details.lower() or "authentication" in error_details.lower()):
31
+ click.echo("Error: Invalid API key or authentication failed", err=True)
32
+ else:
33
+ click.echo(f"Error: {error_details}", err=True)
34
+
35
+ click.echo(f"Error: {e}", err=True)
36
+ return
37
+
38
+
39
+ F = TypeVar("F", bound=Callable[..., Any])
40
+
41
+
42
+ def handle_api_errors(f: F) -> F:
43
+ """Decorator to handle common API errors in CLI commands."""
44
+
45
+ @wraps(f)
46
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
47
+ try:
48
+ return f(*args, **kwargs)
49
+ except APIError as e:
50
+ print_api_error(e)
51
+ sys.exit(1)
52
+ except TogetherError as e:
53
+ print_api_error(e)
54
+ sys.exit(1)
55
+ except Exception as e:
56
+ click.echo(f"Error: An unexpected error occurred - {str(e)}", err=True)
57
+ sys.exit(1)
58
+
59
+ return wrapper # type: ignore
60
+
61
+
62
+ @click.group()
63
+ @click.pass_context
64
+ def evals(ctx: click.Context) -> None:
65
+ """Evals API commands"""
66
+ pass
67
+
68
+
69
+ @evals.command()
70
+ @click.pass_context
71
+ @click.option(
72
+ "--type",
73
+ type=click.Choice(["classify", "score", "compare"]),
74
+ required=True,
75
+ help="Type of evaluation to create.",
76
+ )
77
+ @click.option(
78
+ "--judge-model",
79
+ type=str,
80
+ required=True,
81
+ help="Name or URL of the judge model to use for evaluation.",
82
+ )
83
+ @click.option(
84
+ "--judge-model-source",
85
+ type=click.Choice(["serverless", "dedicated", "external"]),
86
+ required=True,
87
+ help="Source of the judge model.",
88
+ )
89
+ @click.option(
90
+ "--judge-external-api-token",
91
+ type=str,
92
+ required=False,
93
+ help="Optional external API token for the judge model.",
94
+ )
95
+ @click.option(
96
+ "--judge-external-base-url",
97
+ type=str,
98
+ required=False,
99
+ help="Optional external base URLs for the judge model.",
100
+ )
101
+ @click.option(
102
+ "--judge-system-template",
103
+ type=str,
104
+ required=True,
105
+ help="System template for the judge model.",
106
+ )
107
+ @click.option(
108
+ "--input-data-file-path",
109
+ type=str,
110
+ required=True,
111
+ help="Path to the input data file.",
112
+ )
113
+ @click.option(
114
+ "--model-field",
115
+ type=str,
116
+ help="Name of the field in the input file contaning text generated by the model."
117
+ "Can not be used when model-a-name and other model config parameters are specified",
118
+ )
119
+ @click.option(
120
+ "--model-to-evaluate",
121
+ type=str,
122
+ help="Model name when using the detailed config",
123
+ )
124
+ @click.option(
125
+ "--model-to-evaluate-source",
126
+ type=click.Choice(["serverless", "dedicated", "external"]),
127
+ help="Source of the model to evaluate.",
128
+ )
129
+ @click.option(
130
+ "--model-to-evaluate-external-api-token",
131
+ type=str,
132
+ help="Optional external API token for the model to evaluate.",
133
+ )
134
+ @click.option(
135
+ "--model-to-evaluate-external-base-url",
136
+ type=str,
137
+ help="Optional external base URL for the model to evaluate.",
138
+ )
139
+ @click.option(
140
+ "--model-to-evaluate-max-tokens",
141
+ type=int,
142
+ help="Max tokens for model-to-evaluate",
143
+ )
144
+ @click.option(
145
+ "--model-to-evaluate-temperature",
146
+ type=float,
147
+ help="Temperature for model-to-evaluate",
148
+ )
149
+ @click.option(
150
+ "--model-to-evaluate-system-template",
151
+ type=str,
152
+ help="System template for model-to-evaluate",
153
+ )
154
+ @click.option(
155
+ "--model-to-evaluate-input-template",
156
+ type=str,
157
+ help="Input template for model-to-evaluate",
158
+ )
159
+ @click.option(
160
+ "--labels",
161
+ type=str,
162
+ help="Classification labels - comma-separated list",
163
+ )
164
+ @click.option(
165
+ "--pass-labels",
166
+ type=str,
167
+ help="Labels considered as passing (required for classify type). A comma-separated list.",
168
+ )
169
+ @click.option(
170
+ "--min-score",
171
+ type=float,
172
+ help="Minimum score value (required for score type).",
173
+ )
174
+ @click.option(
175
+ "--max-score",
176
+ type=float,
177
+ help="Maximum score value (required for score type).",
178
+ )
179
+ @click.option(
180
+ "--pass-threshold",
181
+ type=float,
182
+ help="Threshold score for passing (required for score type).",
183
+ )
184
+ @click.option(
185
+ "--model-a-field",
186
+ type=str,
187
+ help="Name of the field in the input file containing text generated by Model A. \
188
+ Can not be used when model-a-name and other model config parameters are specified",
189
+ )
190
+ @click.option(
191
+ "--model-a",
192
+ type=str,
193
+ help="Model name or URL for model A when using detailed config.",
194
+ )
195
+ @click.option(
196
+ "--model-a-source",
197
+ type=click.Choice(["serverless", "dedicated", "external"]),
198
+ help="Source of model A.",
199
+ )
200
+ @click.option(
201
+ "--model-a-external-api-token",
202
+ type=str,
203
+ help="Optional external API token for model A.",
204
+ )
205
+ @click.option(
206
+ "--model-a-external-base-url",
207
+ type=str,
208
+ help="Optional external base URL for model A.",
209
+ )
210
+ @click.option(
211
+ "--model-a-max-tokens",
212
+ type=int,
213
+ help="Max tokens for model A.",
214
+ )
215
+ @click.option(
216
+ "--model-a-temperature",
217
+ type=float,
218
+ help="Temperature for model A.",
219
+ )
220
+ @click.option(
221
+ "--model-a-system-template",
222
+ type=str,
223
+ help="System template for model A.",
224
+ )
225
+ @click.option(
226
+ "--model-a-input-template",
227
+ type=str,
228
+ help="Input template for model A.",
229
+ )
230
+ @click.option(
231
+ "--model-b-field",
232
+ type=str,
233
+ help="Name of the field in the input file containing text generated by Model B.\
234
+ Can not be used when model-b-name and other model config parameters are specified",
235
+ )
236
+ @click.option(
237
+ "--model-b",
238
+ type=str,
239
+ help="Model name or URL for model B when using detailed config.",
240
+ )
241
+ @click.option(
242
+ "--model-b-source",
243
+ type=click.Choice(["serverless", "dedicated", "external"]),
244
+ help="Source of model B.",
245
+ )
246
+ @click.option(
247
+ "--model-b-external-api-token",
248
+ type=str,
249
+ help="Optional external API token for model B.",
250
+ )
251
+ @click.option(
252
+ "--model-b-external-base-url",
253
+ type=str,
254
+ help="Optional external base URL for model B.",
255
+ )
256
+ @click.option(
257
+ "--model-b-max-tokens",
258
+ type=int,
259
+ help="Max tokens for model B.",
260
+ )
261
+ @click.option(
262
+ "--model-b-temperature",
263
+ type=float,
264
+ help="Temperature for model B.",
265
+ )
266
+ @click.option(
267
+ "--model-b-system-template",
268
+ type=str,
269
+ help="System template for model B.",
270
+ )
271
+ @click.option(
272
+ "--model-b-input-template",
273
+ type=str,
274
+ help="Input template for model B.",
275
+ )
276
+ @handle_api_errors
277
+ def create(
278
+ ctx: click.Context,
279
+ type: Literal["classify", "score", "compare"],
280
+ judge_model: str,
281
+ judge_model_source: Literal["serverless", "dedicated", "external"],
282
+ judge_system_template: str,
283
+ judge_external_api_token: Optional[str],
284
+ judge_external_base_url: Optional[str],
285
+ input_data_file_path: str,
286
+ model_field: Optional[str],
287
+ model_to_evaluate: Optional[str],
288
+ model_to_evaluate_source: Optional[str],
289
+ model_to_evaluate_external_api_token: Optional[str],
290
+ model_to_evaluate_external_base_url: Optional[str],
291
+ model_to_evaluate_max_tokens: Optional[int],
292
+ model_to_evaluate_temperature: Optional[float],
293
+ model_to_evaluate_system_template: Optional[str],
294
+ model_to_evaluate_input_template: Optional[str],
295
+ labels: str,
296
+ pass_labels: str,
297
+ min_score: Optional[float],
298
+ max_score: Optional[float],
299
+ pass_threshold: Optional[float],
300
+ model_a_field: Optional[str],
301
+ model_a: Optional[str],
302
+ model_a_source: Optional[str],
303
+ model_a_external_api_token: Optional[str],
304
+ model_a_external_base_url: Optional[str],
305
+ model_a_max_tokens: Optional[int],
306
+ model_a_temperature: Optional[float],
307
+ model_a_system_template: Optional[str],
308
+ model_a_input_template: Optional[str],
309
+ model_b_field: Optional[str],
310
+ model_b: Optional[str],
311
+ model_b_source: Optional[str],
312
+ model_b_external_api_token: Optional[str],
313
+ model_b_external_base_url: Optional[str],
314
+ model_b_max_tokens: Optional[int],
315
+ model_b_temperature: Optional[float],
316
+ model_b_system_template: Optional[str],
317
+ model_b_input_template: Optional[str],
318
+ ) -> None:
319
+ """Create a new evaluation job"""
320
+
321
+ client: Together = ctx.obj
322
+
323
+ # Convert strings to lists for labels
324
+ labels_list = labels.split(",") if labels else None
325
+ pass_labels_list = pass_labels.split(",") if pass_labels else None
326
+
327
+ # Build model configurations
328
+ model_to_evaluate_final: Union[Dict[str, Any], None, str] = None
329
+
330
+ # Check if any config parameters are provided
331
+ config_params_provided = any(
332
+ [
333
+ model_to_evaluate,
334
+ model_to_evaluate_source,
335
+ model_to_evaluate_max_tokens,
336
+ model_to_evaluate_temperature,
337
+ model_to_evaluate_system_template,
338
+ model_to_evaluate_input_template,
339
+ ]
340
+ )
341
+
342
+ if model_field:
343
+ # Simple mode: model_field is provided
344
+ if config_params_provided:
345
+ raise click.BadParameter(
346
+ "Cannot specify both --model-field and --model-to-evaluate-* parameters. "
347
+ "Use either --model-field alone if your input file has pre-generated responses, "
348
+ "or config parameters if you want to generate it on our end"
349
+ )
350
+ model_to_evaluate_final = model_field
351
+ elif config_params_provided:
352
+ # Config mode: config parameters are provided
353
+ model_to_evaluate_final = {
354
+ "model": model_to_evaluate,
355
+ "model_source": model_to_evaluate_source,
356
+ "max_tokens": model_to_evaluate_max_tokens,
357
+ "temperature": model_to_evaluate_temperature,
358
+ "system_template": model_to_evaluate_system_template,
359
+ "input_template": model_to_evaluate_input_template,
360
+ }
361
+ if model_to_evaluate_external_api_token:
362
+ model_to_evaluate_final["external_api_token"] = model_to_evaluate_external_api_token
363
+ if model_to_evaluate_external_base_url:
364
+ model_to_evaluate_final["external_base_url"] = model_to_evaluate_external_base_url
365
+
366
+ # Build model-a configuration
367
+ model_a_final: Union[Dict[str, Any], None, str] = None
368
+ model_a_config_params = [
369
+ model_a,
370
+ model_a_source,
371
+ model_a_max_tokens,
372
+ model_a_temperature,
373
+ model_a_system_template,
374
+ model_a_input_template,
375
+ ]
376
+
377
+ if model_a_field is not None:
378
+ # Simple mode: model_a_field is provided
379
+ if any(model_a_config_params):
380
+ raise click.BadParameter(
381
+ "Cannot specify both --model-a-field and config parameters (--model-a-name, etc.). "
382
+ "Use either --model-a-field alone if your input file has pre-generated responses, "
383
+ "or config parameters if you want to generate it on our end"
384
+ )
385
+ model_a_final = model_a_field
386
+ elif any(model_a_config_params):
387
+ # Config mode: config parameters are provided
388
+ model_a_final = {
389
+ "model": model_a,
390
+ "model_source": model_a_source,
391
+ "max_tokens": model_a_max_tokens,
392
+ "temperature": model_a_temperature,
393
+ "system_template": model_a_system_template,
394
+ "input_template": model_a_input_template,
395
+ }
396
+ if model_a_external_api_token:
397
+ model_a_final["external_api_token"] = model_a_external_api_token
398
+ if model_a_external_base_url:
399
+ model_a_final["external_base_url"] = model_a_external_base_url
400
+
401
+ # Build model-b configuration
402
+ model_b_final: Union[Dict[str, Any], None, str] = None
403
+ model_b_config_params = [
404
+ model_b,
405
+ model_b_source,
406
+ model_b_max_tokens,
407
+ model_b_temperature,
408
+ model_b_system_template,
409
+ model_b_input_template,
410
+ ]
411
+
412
+ if model_b_field is not None:
413
+ # Simple mode: model_b_field is provided
414
+ if any(model_b_config_params):
415
+ raise click.BadParameter(
416
+ "Cannot specify both --model-b-field and config parameters (--model-b-name, etc.). "
417
+ "Use either --model-b-field alone if your input file has pre-generated responses, "
418
+ "or config parameters if you want to generate it on our end"
419
+ )
420
+ model_b_final = model_b_field
421
+ elif any(model_b_config_params):
422
+ # Config mode: config parameters are provided
423
+ model_b_final = {
424
+ "model": model_b,
425
+ "model_source": model_b_source,
426
+ "max_tokens": model_b_max_tokens,
427
+ "temperature": model_b_temperature,
428
+ "system_template": model_b_system_template,
429
+ "input_template": model_b_input_template,
430
+ }
431
+ if model_b_external_api_token:
432
+ model_b_final["external_api_token"] = model_b_external_api_token
433
+ if model_b_external_base_url:
434
+ model_b_final["external_base_url"] = model_b_external_base_url
435
+
436
+ judge_config = _build_judge(
437
+ type, judge_model, judge_model_source, judge_system_template, judge_external_api_token, judge_external_base_url
438
+ )
439
+
440
+ if type == "classify":
441
+ response = client.evals.create(
442
+ type=type,
443
+ parameters=ParametersEvaluationClassifyParameters(
444
+ input_data_file_path=input_data_file_path,
445
+ judge=judge_config,
446
+ labels=labels_list or [],
447
+ pass_labels=pass_labels_list or [],
448
+ model_to_evaluate=cast(ParametersEvaluationClassifyParametersModelToEvaluate, model_to_evaluate_final),
449
+ ),
450
+ )
451
+ elif type == "score":
452
+ if max_score is None or min_score is None or pass_threshold is None:
453
+ raise TogetherError("max_score, min_score, and pass_threshold are required for score type")
454
+
455
+ response = client.evals.create(
456
+ type="score",
457
+ parameters=ParametersEvaluationScoreParameters(
458
+ input_data_file_path=input_data_file_path,
459
+ judge=judge_config,
460
+ max_score=max_score,
461
+ min_score=min_score,
462
+ pass_threshold=pass_threshold,
463
+ model_to_evaluate=cast(ParametersEvaluationScoreParametersModelToEvaluate, model_to_evaluate_final),
464
+ ),
465
+ )
466
+ elif type == "compare":
467
+ response = client.evals.create(
468
+ type=type,
469
+ parameters=ParametersEvaluationCompareParameters(
470
+ input_data_file_path=input_data_file_path,
471
+ judge=judge_config,
472
+ model_a=cast(ParametersEvaluationCompareParametersModelAEvaluationModelRequest, model_a_final),
473
+ model_b=cast(ParametersEvaluationCompareParametersModelBEvaluationModelRequest, model_b_final),
474
+ ),
475
+ )
476
+
477
+ click.echo(json.dumps(response.model_dump(exclude_none=True), indent=4))
478
+
479
+
480
+ @evals.command()
481
+ @click.pass_context
482
+ @click.option(
483
+ "--status",
484
+ type=click.Choice(["pending", "queued", "running", "completed", "error", "user_error"]),
485
+ help="Filter by job status.",
486
+ )
487
+ @click.option(
488
+ "--limit",
489
+ type=int,
490
+ help="Limit number of results (max 100).",
491
+ )
492
+ def list(
493
+ ctx: click.Context,
494
+ status: Union[Literal["pending", "queued", "running", "completed", "error", "user_error"], None],
495
+ limit: Union[int, None],
496
+ ) -> None:
497
+ """List evals"""
498
+
499
+ client: Together = ctx.obj
500
+
501
+ response = client.evals.list(status=status or omit, limit=limit or omit)
502
+
503
+ display_list: List[Dict[str, Any]] = []
504
+ for job in response:
505
+ if job.parameters:
506
+ model = job.parameters.get("model_to_evaluate", "")
507
+ model_a = job.parameters.get("model_a", "")
508
+ model_b = job.parameters.get("model_b", "")
509
+ else:
510
+ model = ""
511
+ model_a = ""
512
+ model_b = ""
513
+
514
+ display_list.append(
515
+ {
516
+ "Workflow ID": job.workflow_id or "",
517
+ "Type": job.type,
518
+ "Status": job.status,
519
+ "Created At": job.created_at or 0,
520
+ "Model": model,
521
+ "Model A": model_a,
522
+ "Model B": model_b,
523
+ }
524
+ )
525
+
526
+ table = tabulate(display_list, headers="keys", tablefmt="grid", showindex=True)
527
+ click.echo(table)
528
+
529
+
530
+ @evals.command()
531
+ @click.pass_context
532
+ @click.argument("evaluation_id", type=str, required=True)
533
+ def retrieve(ctx: click.Context, evaluation_id: str) -> None:
534
+ """Get details of a specific evaluation job"""
535
+
536
+ client: Together = ctx.obj
537
+
538
+ response = client.evals.retrieve(evaluation_id)
539
+
540
+ click.echo(json.dumps(response.model_dump(exclude_none=True), default=datetime_serializer, indent=4))
541
+
542
+
543
+ @evals.command()
544
+ @click.pass_context
545
+ @click.argument("evaluation_id", type=str, required=True)
546
+ def status(ctx: click.Context, evaluation_id: str) -> None:
547
+ """Get the status and results of a specific evaluation job"""
548
+
549
+ client: Together = ctx.obj
550
+
551
+ response = client.evals.status(evaluation_id)
552
+
553
+ click.echo(json.dumps(response.model_dump(exclude_none=True), indent=4))
554
+
555
+
556
+ def _build_judge(
557
+ type: Literal["classify", "score", "compare"],
558
+ judge_model: str,
559
+ judge_model_source: Literal["serverless", "dedicated", "external"],
560
+ judge_system_template: str,
561
+ judge_external_api_token: Optional[str],
562
+ judge_external_base_url: Optional[str],
563
+ ) -> ParametersEvaluationClassifyParametersJudge:
564
+ if type == "classify":
565
+ judge_config = ParametersEvaluationClassifyParametersJudge(
566
+ model=judge_model,
567
+ model_source=judge_model_source,
568
+ system_template=judge_system_template,
569
+ )
570
+ elif type == "score":
571
+ judge_config = ParametersEvaluationScoreParametersJudge(
572
+ model=judge_model,
573
+ model_source=judge_model_source,
574
+ system_template=judge_system_template,
575
+ )
576
+ elif type == "compare":
577
+ judge_config = ParametersEvaluationCompareParametersJudge(
578
+ model=judge_model,
579
+ model_source=judge_model_source,
580
+ system_template=judge_system_template,
581
+ )
582
+
583
+ if judge_external_api_token:
584
+ judge_config["external_api_token"] = judge_external_api_token
585
+ if judge_external_base_url:
586
+ judge_config["external_base_url"] = judge_external_base_url
587
+
588
+ return judge_config
@@ -1,5 +1,6 @@
1
1
  import json
2
2
  import pathlib
3
+ from typing import Any, Dict, List, get_args
3
4
  from textwrap import wrap
4
5
 
5
6
  import click
@@ -7,7 +8,9 @@ from tabulate import tabulate
7
8
 
8
9
  from together import Together
9
10
  from together.types import FilePurpose
10
- from together.utils import check_file, convert_bytes, convert_unix_timestamp
11
+
12
+ # from together.utils import check_file, convert_bytes, convert_unix_timestamp
13
+ from ...utils import check_file, convert_bytes, convert_unix_timestamp
11
14
 
12
15
 
13
16
  @click.group()
@@ -21,15 +24,13 @@ def files(ctx: click.Context) -> None:
21
24
  @click.pass_context
22
25
  @click.argument(
23
26
  "file",
24
- type=click.Path(
25
- exists=True, file_okay=True, resolve_path=True, readable=True, dir_okay=False
26
- ),
27
+ type=click.Path(exists=True, file_okay=True, resolve_path=True, readable=True, dir_okay=False),
27
28
  required=True,
28
29
  )
29
30
  @click.option(
30
31
  "--purpose",
31
- type=str,
32
- default=FilePurpose.FineTune.value,
32
+ type=click.Choice(get_args(FilePurpose)),
33
+ default="fine-tune",
33
34
  help="Purpose of file upload. Acceptable values in enum `together.types.FilePurpose`. Defaults to `fine-tunes`.",
34
35
  )
35
36
  @click.option(
@@ -37,7 +38,7 @@ def files(ctx: click.Context) -> None:
37
38
  default=True,
38
39
  help="Whether to check the file before uploading.",
39
40
  )
40
- def upload(ctx: click.Context, file: pathlib.Path, purpose: str, check: bool) -> None:
41
+ def upload(ctx: click.Context, file: pathlib.Path, purpose: FilePurpose, check: bool) -> None:
41
42
  """Upload file"""
42
43
 
43
44
  client: Together = ctx.obj
@@ -55,15 +56,13 @@ def list(ctx: click.Context) -> None:
55
56
 
56
57
  response = client.files.list()
57
58
 
58
- display_list = []
59
+ display_list: List[Dict[str, Any]] = []
59
60
  for i in response.data or []:
60
61
  display_list.append(
61
62
  {
62
63
  "File name": "\n".join(wrap(i.filename or "", width=30)),
63
64
  "File ID": i.id,
64
- "Size": convert_bytes(
65
- float(str(i.bytes))
66
- ), # convert to string for mypy typing
65
+ "Size": convert_bytes(float(str(i.bytes))), # convert to string for mypy typing
67
66
  "Created At": convert_unix_timestamp(i.created_at or 0),
68
67
  "Line Count": i.line_count,
69
68
  }
@@ -95,9 +94,15 @@ def retrieve_content(ctx: click.Context, id: str, output: str) -> None:
95
94
 
96
95
  client: Together = ctx.obj
97
96
 
98
- response = client.files.retrieve_content(id=id, output=output)
97
+ response = client.files.content(id=id)
99
98
 
100
- click.echo(json.dumps(response.model_dump(exclude_none=True), indent=4))
99
+ if output:
100
+ with open(output, "wb") as f:
101
+ f.write(response.read())
102
+ click.echo(f"File saved to {output}")
103
+
104
+ else:
105
+ click.echo(response.read().decode("utf-8"))
101
106
 
102
107
 
103
108
  @files.command()
@@ -117,12 +122,10 @@ def delete(ctx: click.Context, id: str) -> None:
117
122
  @click.pass_context
118
123
  @click.argument(
119
124
  "file",
120
- type=click.Path(
121
- exists=True, file_okay=True, resolve_path=True, readable=True, dir_okay=False
122
- ),
125
+ type=click.Path(exists=True, file_okay=True, resolve_path=True, readable=True, dir_okay=False),
123
126
  required=True,
124
127
  )
125
- def check(ctx: click.Context, file: pathlib.Path) -> None:
128
+ def check(_ctx: click.Context, file: pathlib.Path) -> None:
126
129
  """Check file for issues"""
127
130
 
128
131
  report = check_file(file)