llama-stack-api 0.4.3__py3-none-any.whl → 0.5.0rc1__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 (117) hide show
  1. llama_stack_api/__init__.py +1100 -0
  2. llama_stack_api/admin/__init__.py +45 -0
  3. llama_stack_api/admin/api.py +72 -0
  4. llama_stack_api/admin/fastapi_routes.py +117 -0
  5. llama_stack_api/admin/models.py +113 -0
  6. llama_stack_api/agents/__init__.py +38 -0
  7. llama_stack_api/agents/api.py +52 -0
  8. llama_stack_api/agents/fastapi_routes.py +268 -0
  9. llama_stack_api/agents/models.py +181 -0
  10. llama_stack_api/batches/__init__.py +40 -0
  11. llama_stack_api/batches/api.py +53 -0
  12. llama_stack_api/batches/fastapi_routes.py +113 -0
  13. llama_stack_api/batches/models.py +78 -0
  14. llama_stack_api/benchmarks/__init__.py +43 -0
  15. llama_stack_api/benchmarks/api.py +39 -0
  16. llama_stack_api/benchmarks/fastapi_routes.py +109 -0
  17. llama_stack_api/benchmarks/models.py +109 -0
  18. llama_stack_api/common/__init__.py +5 -0
  19. llama_stack_api/common/content_types.py +101 -0
  20. llama_stack_api/common/errors.py +110 -0
  21. llama_stack_api/common/job_types.py +38 -0
  22. llama_stack_api/common/responses.py +77 -0
  23. llama_stack_api/common/training_types.py +47 -0
  24. llama_stack_api/common/type_system.py +146 -0
  25. llama_stack_api/connectors/__init__.py +38 -0
  26. llama_stack_api/connectors/api.py +50 -0
  27. llama_stack_api/connectors/fastapi_routes.py +103 -0
  28. llama_stack_api/connectors/models.py +103 -0
  29. llama_stack_api/conversations/__init__.py +61 -0
  30. llama_stack_api/conversations/api.py +44 -0
  31. llama_stack_api/conversations/fastapi_routes.py +177 -0
  32. llama_stack_api/conversations/models.py +245 -0
  33. llama_stack_api/datasetio/__init__.py +34 -0
  34. llama_stack_api/datasetio/api.py +42 -0
  35. llama_stack_api/datasetio/fastapi_routes.py +94 -0
  36. llama_stack_api/datasetio/models.py +48 -0
  37. llama_stack_api/datasets/__init__.py +61 -0
  38. llama_stack_api/datasets/api.py +35 -0
  39. llama_stack_api/datasets/fastapi_routes.py +104 -0
  40. llama_stack_api/datasets/models.py +152 -0
  41. llama_stack_api/datatypes.py +373 -0
  42. llama_stack_api/eval/__init__.py +55 -0
  43. llama_stack_api/eval/api.py +51 -0
  44. llama_stack_api/eval/compat.py +300 -0
  45. llama_stack_api/eval/fastapi_routes.py +126 -0
  46. llama_stack_api/eval/models.py +141 -0
  47. llama_stack_api/file_processors/__init__.py +27 -0
  48. llama_stack_api/file_processors/api.py +64 -0
  49. llama_stack_api/file_processors/fastapi_routes.py +78 -0
  50. llama_stack_api/file_processors/models.py +42 -0
  51. llama_stack_api/files/__init__.py +35 -0
  52. llama_stack_api/files/api.py +51 -0
  53. llama_stack_api/files/fastapi_routes.py +124 -0
  54. llama_stack_api/files/models.py +107 -0
  55. llama_stack_api/inference/__init__.py +207 -0
  56. llama_stack_api/inference/api.py +93 -0
  57. llama_stack_api/inference/fastapi_routes.py +243 -0
  58. llama_stack_api/inference/models.py +1035 -0
  59. llama_stack_api/inspect_api/__init__.py +37 -0
  60. llama_stack_api/inspect_api/api.py +25 -0
  61. llama_stack_api/inspect_api/fastapi_routes.py +76 -0
  62. llama_stack_api/inspect_api/models.py +28 -0
  63. llama_stack_api/internal/__init__.py +9 -0
  64. llama_stack_api/internal/kvstore.py +28 -0
  65. llama_stack_api/internal/sqlstore.py +81 -0
  66. llama_stack_api/models/__init__.py +47 -0
  67. llama_stack_api/models/api.py +38 -0
  68. llama_stack_api/models/fastapi_routes.py +104 -0
  69. llama_stack_api/models/models.py +157 -0
  70. llama_stack_api/openai_responses.py +1494 -0
  71. llama_stack_api/post_training/__init__.py +73 -0
  72. llama_stack_api/post_training/api.py +36 -0
  73. llama_stack_api/post_training/fastapi_routes.py +116 -0
  74. llama_stack_api/post_training/models.py +339 -0
  75. llama_stack_api/prompts/__init__.py +47 -0
  76. llama_stack_api/prompts/api.py +44 -0
  77. llama_stack_api/prompts/fastapi_routes.py +163 -0
  78. llama_stack_api/prompts/models.py +177 -0
  79. llama_stack_api/providers/__init__.py +33 -0
  80. llama_stack_api/providers/api.py +16 -0
  81. llama_stack_api/providers/fastapi_routes.py +57 -0
  82. llama_stack_api/providers/models.py +24 -0
  83. llama_stack_api/rag_tool.py +168 -0
  84. llama_stack_api/resource.py +36 -0
  85. llama_stack_api/router_utils.py +160 -0
  86. llama_stack_api/safety/__init__.py +37 -0
  87. llama_stack_api/safety/api.py +29 -0
  88. llama_stack_api/safety/datatypes.py +83 -0
  89. llama_stack_api/safety/fastapi_routes.py +55 -0
  90. llama_stack_api/safety/models.py +38 -0
  91. llama_stack_api/schema_utils.py +251 -0
  92. llama_stack_api/scoring/__init__.py +66 -0
  93. llama_stack_api/scoring/api.py +35 -0
  94. llama_stack_api/scoring/fastapi_routes.py +67 -0
  95. llama_stack_api/scoring/models.py +81 -0
  96. llama_stack_api/scoring_functions/__init__.py +50 -0
  97. llama_stack_api/scoring_functions/api.py +39 -0
  98. llama_stack_api/scoring_functions/fastapi_routes.py +108 -0
  99. llama_stack_api/scoring_functions/models.py +214 -0
  100. llama_stack_api/shields/__init__.py +41 -0
  101. llama_stack_api/shields/api.py +39 -0
  102. llama_stack_api/shields/fastapi_routes.py +104 -0
  103. llama_stack_api/shields/models.py +74 -0
  104. llama_stack_api/tools.py +226 -0
  105. llama_stack_api/validators.py +46 -0
  106. llama_stack_api/vector_io/__init__.py +88 -0
  107. llama_stack_api/vector_io/api.py +234 -0
  108. llama_stack_api/vector_io/fastapi_routes.py +447 -0
  109. llama_stack_api/vector_io/models.py +663 -0
  110. llama_stack_api/vector_stores.py +53 -0
  111. llama_stack_api/version.py +9 -0
  112. {llama_stack_api-0.4.3.dist-info → llama_stack_api-0.5.0rc1.dist-info}/METADATA +1 -1
  113. llama_stack_api-0.5.0rc1.dist-info/RECORD +115 -0
  114. llama_stack_api-0.5.0rc1.dist-info/top_level.txt +1 -0
  115. llama_stack_api-0.4.3.dist-info/RECORD +0 -4
  116. llama_stack_api-0.4.3.dist-info/top_level.txt +0 -1
  117. {llama_stack_api-0.4.3.dist-info → llama_stack_api-0.5.0rc1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,300 @@
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the terms described in the LICENSE file in
5
+ # the root directory of this source tree.
6
+
7
+ """
8
+ Backward compatibility helpers for the Eval API.
9
+
10
+ This module provides utilities to support both the old-style (individual parameters)
11
+ and new-style (request objects) calling conventions for Eval API methods.
12
+
13
+ The old-style parameters are deprecated and will be removed in a future release.
14
+
15
+ Note: When both a request object AND individual parameters are provided, the request
16
+ object takes precedence and individual parameters are ignored.
17
+ """
18
+
19
+ import warnings
20
+ from typing import Any
21
+
22
+ from .models import (
23
+ BenchmarkConfig,
24
+ EvaluateRowsRequest,
25
+ JobCancelRequest,
26
+ JobResultRequest,
27
+ JobStatusRequest,
28
+ RunEvalRequest,
29
+ )
30
+
31
+ _DEPRECATION_TARGET = "0.6.0"
32
+
33
+ _DEPRECATION_MESSAGE = (
34
+ "Passing individual parameters to {method_name}() is deprecated. "
35
+ "Please use {request_class}(benchmark_id=..., ...) instead. "
36
+ "This will be removed in version {target}."
37
+ )
38
+
39
+
40
+ def _emit_deprecation_warning(method_name: str, request_class: str) -> None:
41
+ """Emit a deprecation warning for old-style parameter usage."""
42
+ warnings.warn(
43
+ _DEPRECATION_MESSAGE.format(method_name=method_name, request_class=request_class, target=_DEPRECATION_TARGET),
44
+ DeprecationWarning,
45
+ stacklevel=4,
46
+ )
47
+
48
+
49
+ def _format_missing_params(required: list[str], provided: dict[str, Any]) -> str:
50
+ """Format error message showing which parameters are missing."""
51
+ missing = [p for p in required if provided.get(p) is None]
52
+ provided_names = [p for p in required if provided.get(p) is not None]
53
+
54
+ parts = []
55
+ if missing:
56
+ parts.append(f"missing: {', '.join(missing)}")
57
+ if provided_names:
58
+ parts.append(f"provided: {', '.join(provided_names)}")
59
+
60
+ return "; ".join(parts)
61
+
62
+
63
+ def _validate_not_empty(value: Any, name: str) -> None:
64
+ """Validate that a value is not None, empty string, or empty list."""
65
+ if not value:
66
+ raise ValueError(f"'{name}' cannot be None or empty. Provided: {value}")
67
+
68
+
69
+ def resolve_run_eval_request(
70
+ request: RunEvalRequest | None = None,
71
+ *,
72
+ benchmark_id: str | None = None,
73
+ benchmark_config: BenchmarkConfig | None = None,
74
+ ) -> RunEvalRequest:
75
+ """
76
+ Resolve run_eval parameters to a RunEvalRequest object.
77
+
78
+ Supports both new-style (request object) and old-style (individual parameters).
79
+ Old-style usage emits a DeprecationWarning.
80
+
81
+ Note: If both request object and individual parameters are provided, the request
82
+ object takes precedence and individual parameters are ignored.
83
+
84
+ Args:
85
+ request: The new-style request object (preferred)
86
+ benchmark_id: (Deprecated) The benchmark ID
87
+ benchmark_config: (Deprecated) The benchmark configuration
88
+
89
+ Returns:
90
+ RunEvalRequest object
91
+ """
92
+ if request is not None:
93
+ _validate_not_empty(request.benchmark_id, "benchmark_id")
94
+ _validate_not_empty(request.benchmark_config, "benchmark_config")
95
+ return request
96
+
97
+ # Old-style parameters
98
+ if benchmark_id and benchmark_config:
99
+ _emit_deprecation_warning("run_eval", "RunEvalRequest")
100
+ return RunEvalRequest(
101
+ benchmark_id=benchmark_id,
102
+ benchmark_config=benchmark_config,
103
+ )
104
+
105
+ required = ["benchmark_id", "benchmark_config"]
106
+ provided = {"benchmark_id": benchmark_id, "benchmark_config": benchmark_config}
107
+ raise ValueError(
108
+ f"Either 'request' (RunEvalRequest) or both 'benchmark_id' and 'benchmark_config' "
109
+ f"must be provided. {_format_missing_params(required, provided)}"
110
+ )
111
+
112
+
113
+ def resolve_evaluate_rows_request(
114
+ request: EvaluateRowsRequest | None = None,
115
+ *,
116
+ benchmark_id: str | None = None,
117
+ input_rows: list[dict[str, Any]] | None = None,
118
+ scoring_functions: list[str] | None = None,
119
+ benchmark_config: BenchmarkConfig | None = None,
120
+ ) -> EvaluateRowsRequest:
121
+ """
122
+ Resolve evaluate_rows parameters to an EvaluateRowsRequest object.
123
+
124
+ Supports both new-style (request object) and old-style (individual parameters).
125
+ Old-style usage emits a DeprecationWarning.
126
+
127
+ Note: If both request object and individual parameters are provided, the request
128
+ object takes precedence and individual parameters are ignored.
129
+
130
+ Args:
131
+ request: The new-style request object (preferred)
132
+ benchmark_id: (Deprecated) The benchmark ID
133
+ input_rows: (Deprecated) The rows to evaluate
134
+ scoring_functions: (Deprecated) The scoring functions to use
135
+ benchmark_config: (Deprecated) The benchmark configuration
136
+
137
+ Returns:
138
+ EvaluateRowsRequest object
139
+ """
140
+ if request is not None:
141
+ _validate_not_empty(request.benchmark_id, "benchmark_id")
142
+ _validate_not_empty(request.input_rows, "input_rows")
143
+ _validate_not_empty(request.scoring_functions, "scoring_functions")
144
+ _validate_not_empty(request.benchmark_config, "benchmark_config")
145
+ return request
146
+
147
+ # Old-style parameters
148
+ if benchmark_id and input_rows and scoring_functions and benchmark_config:
149
+ _emit_deprecation_warning("evaluate_rows", "EvaluateRowsRequest")
150
+ return EvaluateRowsRequest(
151
+ benchmark_id=benchmark_id,
152
+ input_rows=input_rows,
153
+ scoring_functions=scoring_functions,
154
+ benchmark_config=benchmark_config,
155
+ )
156
+
157
+ required = ["benchmark_id", "input_rows", "scoring_functions", "benchmark_config"]
158
+ provided = {
159
+ "benchmark_id": benchmark_id,
160
+ "input_rows": input_rows,
161
+ "scoring_functions": scoring_functions,
162
+ "benchmark_config": benchmark_config,
163
+ }
164
+ raise ValueError(
165
+ f"Either 'request' (EvaluateRowsRequest) or all of 'benchmark_id', 'input_rows', "
166
+ f"'scoring_functions', and 'benchmark_config' must be provided. "
167
+ f"{_format_missing_params(required, provided)}"
168
+ )
169
+
170
+
171
+ def resolve_job_status_request(
172
+ request: JobStatusRequest | None = None,
173
+ *,
174
+ benchmark_id: str | None = None,
175
+ job_id: str | None = None,
176
+ ) -> JobStatusRequest:
177
+ """
178
+ Resolve job_status parameters to a JobStatusRequest object.
179
+
180
+ Supports both new-style (request object) and old-style (individual parameters).
181
+ Old-style usage emits a DeprecationWarning.
182
+
183
+ Note: If both request object and individual parameters are provided, the request
184
+ object takes precedence and individual parameters are ignored.
185
+
186
+ Args:
187
+ request: The new-style request object (preferred)
188
+ benchmark_id: (Deprecated) The benchmark ID
189
+ job_id: (Deprecated) The job ID
190
+
191
+ Returns:
192
+ JobStatusRequest object
193
+ """
194
+ if request is not None:
195
+ _validate_not_empty(request.benchmark_id, "benchmark_id")
196
+ _validate_not_empty(request.job_id, "job_id")
197
+ return request
198
+
199
+ # Old-style parameters
200
+ if benchmark_id and job_id:
201
+ _emit_deprecation_warning("job_status", "JobStatusRequest")
202
+ return JobStatusRequest(
203
+ benchmark_id=benchmark_id,
204
+ job_id=job_id,
205
+ )
206
+
207
+ required = ["benchmark_id", "job_id"]
208
+ provided = {"benchmark_id": benchmark_id, "job_id": job_id}
209
+ raise ValueError(
210
+ f"Either 'request' (JobStatusRequest) or both 'benchmark_id' and 'job_id' "
211
+ f"must be provided. {_format_missing_params(required, provided)}"
212
+ )
213
+
214
+
215
+ def resolve_job_cancel_request(
216
+ request: JobCancelRequest | None = None,
217
+ *,
218
+ benchmark_id: str | None = None,
219
+ job_id: str | None = None,
220
+ ) -> JobCancelRequest:
221
+ """
222
+ Resolve job_cancel parameters to a JobCancelRequest object.
223
+
224
+ Supports both new-style (request object) and old-style (individual parameters).
225
+ Old-style usage emits a DeprecationWarning.
226
+
227
+ Note: If both request object and individual parameters are provided, the request
228
+ object takes precedence and individual parameters are ignored.
229
+
230
+ Args:
231
+ request: The new-style request object (preferred)
232
+ benchmark_id: (Deprecated) The benchmark ID
233
+ job_id: (Deprecated) The job ID
234
+
235
+ Returns:
236
+ JobCancelRequest object
237
+ """
238
+ if request is not None:
239
+ _validate_not_empty(request.benchmark_id, "benchmark_id")
240
+ _validate_not_empty(request.job_id, "job_id")
241
+ return request
242
+
243
+ # Old-style parameters
244
+ if benchmark_id and job_id:
245
+ _emit_deprecation_warning("job_cancel", "JobCancelRequest")
246
+ return JobCancelRequest(
247
+ benchmark_id=benchmark_id,
248
+ job_id=job_id,
249
+ )
250
+
251
+ required = ["benchmark_id", "job_id"]
252
+ provided = {"benchmark_id": benchmark_id, "job_id": job_id}
253
+ raise ValueError(
254
+ f"Either 'request' (JobCancelRequest) or both 'benchmark_id' and 'job_id' "
255
+ f"must be provided. {_format_missing_params(required, provided)}"
256
+ )
257
+
258
+
259
+ def resolve_job_result_request(
260
+ request: JobResultRequest | None = None,
261
+ *,
262
+ benchmark_id: str | None = None,
263
+ job_id: str | None = None,
264
+ ) -> JobResultRequest:
265
+ """
266
+ Resolve job_result parameters to a JobResultRequest object.
267
+
268
+ Supports both new-style (request object) and old-style (individual parameters).
269
+ Old-style usage emits a DeprecationWarning.
270
+
271
+ Note: If both request object and individual parameters are provided, the request
272
+ object takes precedence and individual parameters are ignored.
273
+
274
+ Args:
275
+ request: The new-style request object (preferred)
276
+ benchmark_id: (Deprecated) The benchmark ID
277
+ job_id: (Deprecated) The job ID
278
+
279
+ Returns:
280
+ JobResultRequest object
281
+ """
282
+ if request is not None:
283
+ _validate_not_empty(request.benchmark_id, "benchmark_id")
284
+ _validate_not_empty(request.job_id, "job_id")
285
+ return request
286
+
287
+ # Old-style parameters
288
+ if benchmark_id and job_id:
289
+ _emit_deprecation_warning("job_result", "JobResultRequest")
290
+ return JobResultRequest(
291
+ benchmark_id=benchmark_id,
292
+ job_id=job_id,
293
+ )
294
+
295
+ required = ["benchmark_id", "job_id"]
296
+ provided = {"benchmark_id": benchmark_id, "job_id": job_id}
297
+ raise ValueError(
298
+ f"Either 'request' (JobResultRequest) or both 'benchmark_id' and 'job_id' "
299
+ f"must be provided. {_format_missing_params(required, provided)}"
300
+ )
@@ -0,0 +1,126 @@
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the terms described in the LICENSE file in
5
+ # the root directory of this source tree.
6
+
7
+ from typing import Annotated
8
+
9
+ from fastapi import APIRouter, Body, Depends
10
+
11
+ from llama_stack_api.common.job_types import Job
12
+ from llama_stack_api.router_utils import create_path_dependency, standard_responses
13
+ from llama_stack_api.version import LLAMA_STACK_API_V1ALPHA
14
+
15
+ from .api import Eval
16
+ from .models import (
17
+ BenchmarkIdRequest,
18
+ EvaluateResponse,
19
+ EvaluateRowsBodyRequest,
20
+ EvaluateRowsRequest,
21
+ JobCancelRequest,
22
+ JobResultRequest,
23
+ JobStatusRequest,
24
+ RunEvalBodyRequest,
25
+ RunEvalRequest,
26
+ )
27
+
28
+ get_benchmark_id_request = create_path_dependency(BenchmarkIdRequest)
29
+
30
+
31
+ def create_router(impl: Eval) -> APIRouter:
32
+ """Create a FastAPI router for the Eval API."""
33
+ router = APIRouter(
34
+ prefix=f"/{LLAMA_STACK_API_V1ALPHA}",
35
+ tags=["Eval"],
36
+ responses=standard_responses,
37
+ )
38
+
39
+ @router.post(
40
+ "/eval/benchmarks/{benchmark_id}/jobs",
41
+ response_model=Job,
42
+ summary="Run Eval",
43
+ description="Run an evaluation on a benchmark.",
44
+ responses={
45
+ 200: {"description": "The job that was created to run the evaluation."},
46
+ },
47
+ )
48
+ async def run_eval(
49
+ benchmark_id_request: Annotated[BenchmarkIdRequest, Depends(get_benchmark_id_request)],
50
+ body_request: Annotated[RunEvalBodyRequest, Body(...)],
51
+ ) -> Job:
52
+ request = RunEvalRequest(
53
+ benchmark_id=benchmark_id_request.benchmark_id,
54
+ benchmark_config=body_request.benchmark_config,
55
+ )
56
+ return await impl.run_eval(request)
57
+
58
+ @router.post(
59
+ "/eval/benchmarks/{benchmark_id}/evaluations",
60
+ response_model=EvaluateResponse,
61
+ summary="Evaluate Rows",
62
+ description="Evaluate a list of rows on a benchmark.",
63
+ responses={
64
+ 200: {"description": "EvaluateResponse object containing generations and scores."},
65
+ },
66
+ )
67
+ async def evaluate_rows(
68
+ benchmark_id_request: Annotated[BenchmarkIdRequest, Depends(get_benchmark_id_request)],
69
+ body_request: Annotated[EvaluateRowsBodyRequest, Body(...)],
70
+ ) -> EvaluateResponse:
71
+ request = EvaluateRowsRequest(
72
+ benchmark_id=benchmark_id_request.benchmark_id,
73
+ input_rows=body_request.input_rows,
74
+ scoring_functions=body_request.scoring_functions,
75
+ benchmark_config=body_request.benchmark_config,
76
+ )
77
+ return await impl.evaluate_rows(request)
78
+
79
+ @router.get(
80
+ "/eval/benchmarks/{benchmark_id}/jobs/{job_id}",
81
+ response_model=Job,
82
+ summary="Job Status",
83
+ description="Get the status of a job.",
84
+ responses={
85
+ 200: {"description": "The status of the evaluation job."},
86
+ },
87
+ )
88
+ async def job_status(
89
+ benchmark_id: str,
90
+ job_id: str,
91
+ ) -> Job:
92
+ request = JobStatusRequest(benchmark_id=benchmark_id, job_id=job_id)
93
+ return await impl.job_status(request)
94
+
95
+ @router.delete(
96
+ "/eval/benchmarks/{benchmark_id}/jobs/{job_id}",
97
+ summary="Job Cancel",
98
+ description="Cancel a job.",
99
+ responses={
100
+ 200: {"description": "Successful Response"},
101
+ },
102
+ )
103
+ async def job_cancel(
104
+ benchmark_id: str,
105
+ job_id: str,
106
+ ) -> None:
107
+ request = JobCancelRequest(benchmark_id=benchmark_id, job_id=job_id)
108
+ return await impl.job_cancel(request)
109
+
110
+ @router.get(
111
+ "/eval/benchmarks/{benchmark_id}/jobs/{job_id}/result",
112
+ response_model=EvaluateResponse,
113
+ summary="Job Result",
114
+ description="Get the result of a job.",
115
+ responses={
116
+ 200: {"description": "The result of the job."},
117
+ },
118
+ )
119
+ async def job_result(
120
+ benchmark_id: str,
121
+ job_id: str,
122
+ ) -> EvaluateResponse:
123
+ request = JobResultRequest(benchmark_id=benchmark_id, job_id=job_id)
124
+ return await impl.job_result(request)
125
+
126
+ return router
@@ -0,0 +1,141 @@
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the terms described in the LICENSE file in
5
+ # the root directory of this source tree.
6
+
7
+ from typing import Any, Literal
8
+
9
+ from pydantic import BaseModel, Field
10
+
11
+ from llama_stack_api.inference import SamplingParams, SystemMessage
12
+ from llama_stack_api.schema_utils import json_schema_type
13
+ from llama_stack_api.scoring import ScoringResult
14
+ from llama_stack_api.scoring_functions import ScoringFnParams
15
+
16
+
17
+ @json_schema_type
18
+ class ModelCandidate(BaseModel):
19
+ """A model candidate for evaluation."""
20
+
21
+ type: Literal["model"] = "model"
22
+ model: str = Field(..., description="The model ID to evaluate", min_length=1)
23
+ sampling_params: SamplingParams = Field(..., description="The sampling parameters for the model")
24
+ system_message: SystemMessage | None = Field(
25
+ None, description="The system message providing instructions or context to the model"
26
+ )
27
+
28
+
29
+ EvalCandidate = ModelCandidate
30
+
31
+
32
+ @json_schema_type
33
+ class BenchmarkConfig(BaseModel):
34
+ """A benchmark configuration for evaluation."""
35
+
36
+ eval_candidate: EvalCandidate = Field(..., description="The candidate to evaluate")
37
+ scoring_params: dict[str, ScoringFnParams] = Field(
38
+ default_factory=dict,
39
+ description="Map between scoring function id and parameters for each scoring function you want to run",
40
+ )
41
+ num_examples: int | None = Field(
42
+ None,
43
+ description="Number of examples to evaluate (useful for testing), if not provided, all examples in the dataset will be evaluated",
44
+ ge=1,
45
+ )
46
+ # we could optinally add any specific dataset config here
47
+
48
+
49
+ @json_schema_type
50
+ class EvaluateResponse(BaseModel):
51
+ """The response from an evaluation."""
52
+
53
+ generations: list[dict[str, Any]] = Field(..., description="The generations from the evaluation")
54
+ scores: dict[str, ScoringResult] = Field(
55
+ ..., description="The scores from the evaluation. Each key in the dict is a scoring function name"
56
+ )
57
+
58
+
59
+ @json_schema_type
60
+ class BenchmarkIdRequest(BaseModel):
61
+ """Request model containing benchmark_id path parameter."""
62
+
63
+ benchmark_id: str = Field(..., description="The ID of the benchmark", min_length=1)
64
+
65
+
66
+ @json_schema_type
67
+ class RunEvalRequest(BaseModel):
68
+ """Request model for running an evaluation on a benchmark."""
69
+
70
+ benchmark_id: str = Field(..., description="The ID of the benchmark to run the evaluation on", min_length=1)
71
+ benchmark_config: BenchmarkConfig = Field(..., description="The configuration for the benchmark")
72
+
73
+
74
+ @json_schema_type
75
+ class RunEvalBodyRequest(BaseModel):
76
+ """Request body model for running an evaluation (without path parameter)."""
77
+
78
+ benchmark_config: BenchmarkConfig = Field(..., description="The configuration for the benchmark")
79
+
80
+
81
+ @json_schema_type
82
+ class EvaluateRowsRequest(BaseModel):
83
+ """Request model for evaluating a list of rows on a benchmark."""
84
+
85
+ benchmark_id: str = Field(..., description="The ID of the benchmark to run the evaluation on", min_length=1)
86
+ input_rows: list[dict[str, Any]] = Field(..., description="The rows to evaluate", min_length=1)
87
+ scoring_functions: list[str] = Field(
88
+ ..., description="The scoring functions to use for the evaluation", min_length=1
89
+ )
90
+ benchmark_config: BenchmarkConfig = Field(..., description="The configuration for the benchmark")
91
+
92
+
93
+ @json_schema_type
94
+ class EvaluateRowsBodyRequest(BaseModel):
95
+ """Request body model for evaluating rows (without path parameter)."""
96
+
97
+ input_rows: list[dict[str, Any]] = Field(..., description="The rows to evaluate", min_length=1)
98
+ scoring_functions: list[str] = Field(
99
+ ..., description="The scoring functions to use for the evaluation", min_length=1
100
+ )
101
+ benchmark_config: BenchmarkConfig = Field(..., description="The configuration for the benchmark")
102
+
103
+
104
+ @json_schema_type
105
+ class JobStatusRequest(BaseModel):
106
+ """Request model for getting the status of a job."""
107
+
108
+ benchmark_id: str = Field(..., description="The ID of the benchmark associated with the job", min_length=1)
109
+ job_id: str = Field(..., description="The ID of the job to get the status of", min_length=1)
110
+
111
+
112
+ @json_schema_type
113
+ class JobCancelRequest(BaseModel):
114
+ """Request model for canceling a job."""
115
+
116
+ benchmark_id: str = Field(..., description="The ID of the benchmark associated with the job", min_length=1)
117
+ job_id: str = Field(..., description="The ID of the job to cancel", min_length=1)
118
+
119
+
120
+ @json_schema_type
121
+ class JobResultRequest(BaseModel):
122
+ """Request model for getting the result of a job."""
123
+
124
+ benchmark_id: str = Field(..., description="The ID of the benchmark associated with the job", min_length=1)
125
+ job_id: str = Field(..., description="The ID of the job to get the result of", min_length=1)
126
+
127
+
128
+ __all__ = [
129
+ "ModelCandidate",
130
+ "EvalCandidate",
131
+ "BenchmarkConfig",
132
+ "EvaluateResponse",
133
+ "BenchmarkIdRequest",
134
+ "RunEvalRequest",
135
+ "RunEvalBodyRequest",
136
+ "EvaluateRowsRequest",
137
+ "EvaluateRowsBodyRequest",
138
+ "JobStatusRequest",
139
+ "JobCancelRequest",
140
+ "JobResultRequest",
141
+ ]
@@ -0,0 +1,27 @@
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the terms described in the LICENSE file in
5
+ # the root directory of this source tree.
6
+
7
+ """File Processors API protocol and models.
8
+
9
+ This module contains the File Processors protocol definition.
10
+ Pydantic models are defined in llama_stack_api.file_processors.models.
11
+ The FastAPI router is defined in llama_stack_api.file_processors.fastapi_routes.
12
+ """
13
+
14
+ # Import fastapi_routes for router factory access
15
+ from . import fastapi_routes
16
+
17
+ # Import protocol for re-export
18
+ from .api import FileProcessors
19
+
20
+ # Import models for re-export
21
+ from .models import ProcessFileResponse
22
+
23
+ __all__ = [
24
+ "FileProcessors",
25
+ "ProcessFileResponse",
26
+ "fastapi_routes",
27
+ ]
@@ -0,0 +1,64 @@
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # All rights reserved.
3
+ #
4
+ # This source code is licensed under the terms described in the LICENSE file in
5
+ # the root directory of this source tree.
6
+
7
+ from typing import Any, Protocol, runtime_checkable
8
+
9
+ from fastapi import UploadFile
10
+
11
+ from llama_stack_api.vector_io import VectorStoreChunkingStrategy
12
+
13
+ from .models import ProcessFileResponse
14
+
15
+
16
+ @runtime_checkable
17
+ class FileProcessors(Protocol):
18
+ """
19
+ File Processor API for converting files into structured, processable content.
20
+
21
+ This API provides a flexible interface for processing various file formats
22
+ (PDFs, documents, images, etc.) into normalized text content that can be used for
23
+ vector store ingestion, RAG applications, or standalone content extraction.
24
+
25
+ The API focuses on parsing and normalization:
26
+ - Multiple file formats through extensible provider architecture
27
+ - Multipart form uploads or file ID references
28
+ - Configurable processing options per provider
29
+ - Optional chunking using provider's native capabilities
30
+ - Rich metadata about processing results
31
+
32
+ For embedding generation, use the chunks from this API with the separate
33
+ embedding API to maintain clean separation of concerns.
34
+
35
+ Future providers can extend this interface to support additional formats,
36
+ processing capabilities, and optimization strategies.
37
+ """
38
+
39
+ async def process_file(
40
+ self,
41
+ file: UploadFile | None = None,
42
+ file_id: str | None = None,
43
+ options: dict[str, Any] | None = None,
44
+ chunking_strategy: VectorStoreChunkingStrategy | None = None,
45
+ ) -> ProcessFileResponse:
46
+ """
47
+ Process a file into chunks ready for vector database storage.
48
+
49
+ This method supports two modes of operation via multipart form request:
50
+ 1. Direct upload: Upload and process a file directly (file parameter)
51
+ 2. File storage: Process files already uploaded to file storage (file_id parameter)
52
+
53
+ Exactly one of file or file_id must be provided.
54
+
55
+ If no chunking_strategy is provided, the entire file content is returned as a single chunk.
56
+ If chunking_strategy is provided, the file is split according to the strategy.
57
+
58
+ :param file: The uploaded file object containing content and metadata (filename, content_type, etc.). Mutually exclusive with file_id.
59
+ :param file_id: ID of file already uploaded to file storage. Mutually exclusive with file.
60
+ :param options: Provider-specific processing options (e.g., OCR settings, output format).
61
+ :param chunking_strategy: Optional strategy for splitting content into chunks.
62
+ :returns: ProcessFileResponse with chunks ready for vector database storage.
63
+ """
64
+ ...