qtype 0.1.6__py3-none-any.whl → 0.1.8__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.
- qtype/base/types.py +1 -9
- qtype/base/ui_shapes.py +38 -0
- qtype/dsl/model.py +43 -18
- qtype/interpreter/base/base_step_executor.py +10 -10
- qtype/interpreter/base/factory.py +6 -0
- qtype/interpreter/base/step_cache.py +3 -3
- qtype/interpreter/conversions.py +7 -4
- qtype/interpreter/executors/agent_executor.py +1 -2
- qtype/interpreter/executors/bedrock_reranker_executor.py +1 -2
- qtype/interpreter/executors/collect_executor.py +76 -0
- qtype/interpreter/executors/construct_executor.py +68 -0
- qtype/interpreter/executors/decoder_executor.py +1 -2
- qtype/interpreter/executors/doc_to_text_executor.py +1 -2
- qtype/interpreter/executors/document_embedder_executor.py +1 -2
- qtype/interpreter/executors/document_search_executor.py +1 -2
- qtype/interpreter/executors/document_source_executor.py +1 -2
- qtype/interpreter/executors/document_splitter_executor.py +1 -2
- qtype/interpreter/executors/echo_executor.py +1 -2
- qtype/interpreter/executors/explode_executor.py +49 -0
- qtype/interpreter/executors/field_extractor_executor.py +1 -2
- qtype/interpreter/executors/file_writer_executor.py +12 -13
- qtype/interpreter/executors/index_upsert_executor.py +3 -4
- qtype/interpreter/executors/invoke_embedding_executor.py +1 -2
- qtype/interpreter/executors/invoke_tool_executor.py +1 -2
- qtype/interpreter/executors/llm_inference_executor.py +1 -2
- qtype/interpreter/executors/prompt_template_executor.py +1 -2
- qtype/interpreter/executors/sql_source_executor.py +1 -2
- qtype/interpreter/executors/vector_search_executor.py +1 -2
- qtype/interpreter/flow.py +6 -4
- qtype/interpreter/types.py +18 -10
- qtype/interpreter/typing.py +53 -4
- qtype/semantic/checker.py +83 -0
- qtype/semantic/generate.py +0 -1
- qtype/semantic/model.py +25 -18
- {qtype-0.1.6.dist-info → qtype-0.1.8.dist-info}/METADATA +2 -2
- {qtype-0.1.6.dist-info → qtype-0.1.8.dist-info}/RECORD +40 -36
- {qtype-0.1.6.dist-info → qtype-0.1.8.dist-info}/WHEEL +0 -0
- {qtype-0.1.6.dist-info → qtype-0.1.8.dist-info}/entry_points.txt +0 -0
- {qtype-0.1.6.dist-info → qtype-0.1.8.dist-info}/licenses/LICENSE +0 -0
- {qtype-0.1.6.dist-info → qtype-0.1.8.dist-info}/top_level.txt +0 -0
|
@@ -100,8 +100,7 @@ class IndexUpsertExecutor(BatchedStepExecutor):
|
|
|
100
100
|
|
|
101
101
|
# Mark all messages with the error and yield them
|
|
102
102
|
for message in batch:
|
|
103
|
-
message.
|
|
104
|
-
yield message
|
|
103
|
+
yield message.copy_with_error(self.step.id, e)
|
|
105
104
|
|
|
106
105
|
async def _upsert_to_vector_store(
|
|
107
106
|
self, batch: list[FlowMessage]
|
|
@@ -220,13 +219,13 @@ class IndexUpsertExecutor(BatchedStepExecutor):
|
|
|
220
219
|
doc_id = item["index"]["_id"]
|
|
221
220
|
message = message_by_id[doc_id]
|
|
222
221
|
if "error" in item.get("index", {}):
|
|
223
|
-
message.
|
|
222
|
+
yield message.copy_with_error(
|
|
224
223
|
self.step.id,
|
|
225
224
|
Exception(item["index"]["error"]),
|
|
226
225
|
)
|
|
227
226
|
else:
|
|
228
227
|
num_inserted += 1
|
|
229
|
-
|
|
228
|
+
yield message
|
|
230
229
|
await self.stream_emitter.status(
|
|
231
230
|
f"Upserted {num_inserted} items to index {self.step.index.name}, {len(batch) - num_inserted} errors occurred."
|
|
232
231
|
)
|
|
@@ -100,5 +100,4 @@ class InvokeEmbeddingExecutor(StepExecutor):
|
|
|
100
100
|
except Exception as e:
|
|
101
101
|
# Emit error event to stream so frontend can display it
|
|
102
102
|
await self.stream_emitter.error(str(e))
|
|
103
|
-
message.
|
|
104
|
-
yield message
|
|
103
|
+
yield message.copy_with_error(self.step.id, e)
|
|
@@ -354,5 +354,4 @@ class InvokeToolExecutor(StepExecutor, ToolExecutionMixin):
|
|
|
354
354
|
except Exception as e:
|
|
355
355
|
# Emit error event to stream so frontend can display it
|
|
356
356
|
await self.stream_emitter.error(str(e))
|
|
357
|
-
message.
|
|
358
|
-
yield message
|
|
357
|
+
yield message.copy_with_error(self.step.id, e)
|
|
@@ -86,8 +86,7 @@ class LLMInferenceExecutor(StepExecutor):
|
|
|
86
86
|
except Exception as e:
|
|
87
87
|
# Emit error event to stream so frontend can display it
|
|
88
88
|
await self.stream_emitter.error(str(e))
|
|
89
|
-
message.
|
|
90
|
-
yield message
|
|
89
|
+
yield message.copy_with_error(self.step.id, e)
|
|
91
90
|
|
|
92
91
|
async def _process_chat(
|
|
93
92
|
self,
|
|
@@ -74,5 +74,4 @@ class PromptTemplateExecutor(StepExecutor):
|
|
|
74
74
|
except Exception as e:
|
|
75
75
|
# Emit error event to stream so frontend can display it
|
|
76
76
|
await self.stream_emitter.error(str(e))
|
|
77
|
-
message.
|
|
78
|
-
yield message
|
|
77
|
+
yield message.copy_with_error(self.step.id, e)
|
|
@@ -102,5 +102,4 @@ class SQLSourceExecutor(StepExecutor):
|
|
|
102
102
|
# Emit error event to stream so frontend can display it
|
|
103
103
|
await self.stream_emitter.error(str(e))
|
|
104
104
|
# Set error on the message and yield it
|
|
105
|
-
message.
|
|
106
|
-
yield message
|
|
105
|
+
yield message.copy_with_error(self.step.id, e)
|
|
@@ -87,5 +87,4 @@ class VectorSearchExecutor(StepExecutor):
|
|
|
87
87
|
logger.error(f"Vector search failed: {e}", exc_info=True)
|
|
88
88
|
# Emit error event to stream so frontend can display it
|
|
89
89
|
await self.stream_emitter.error(str(e))
|
|
90
|
-
message.
|
|
91
|
-
yield message
|
|
90
|
+
yield message.copy_with_error(self.step.id, e)
|
qtype/interpreter/flow.py
CHANGED
|
@@ -12,13 +12,12 @@ from opentelemetry import context as otel_context
|
|
|
12
12
|
from opentelemetry import trace
|
|
13
13
|
from opentelemetry.trace import Status, StatusCode
|
|
14
14
|
from rich.console import Console
|
|
15
|
-
from transformers import ProgressCallback
|
|
16
15
|
|
|
17
16
|
from qtype.interpreter.base import factory
|
|
18
17
|
from qtype.interpreter.base.executor_context import ExecutorContext
|
|
19
18
|
from qtype.interpreter.logging_progress import LoggingProgressCallback
|
|
20
19
|
from qtype.interpreter.rich_progress import RichProgressCallback
|
|
21
|
-
from qtype.interpreter.types import FlowMessage
|
|
20
|
+
from qtype.interpreter.types import FlowMessage, ProgressCallback
|
|
22
21
|
from qtype.semantic.model import Flow
|
|
23
22
|
|
|
24
23
|
logger = logging.getLogger(__name__)
|
|
@@ -57,12 +56,15 @@ async def run_flow(
|
|
|
57
56
|
# Extract or create ExecutorContext
|
|
58
57
|
exec_context = kwargs.pop("context", None)
|
|
59
58
|
if exec_context is None:
|
|
59
|
+
# Track if we created the context so we know to clean it up
|
|
60
|
+
should_clean_context = True
|
|
60
61
|
exec_context = ExecutorContext(
|
|
61
62
|
secret_manager=NoOpSecretManager(),
|
|
62
63
|
tracer=trace.get_tracer(__name__),
|
|
63
64
|
on_progress=progress_callback,
|
|
64
65
|
)
|
|
65
66
|
else:
|
|
67
|
+
should_clean_context = False
|
|
66
68
|
if exec_context.on_progress is None and show_progress:
|
|
67
69
|
exec_context.on_progress = progress_callback
|
|
68
70
|
|
|
@@ -178,8 +180,8 @@ async def run_flow(
|
|
|
178
180
|
span.set_status(Status(StatusCode.ERROR, f"Flow failed: {e}"))
|
|
179
181
|
raise
|
|
180
182
|
finally:
|
|
181
|
-
# Clean up context resources if we created it
|
|
182
|
-
if
|
|
183
|
+
# Clean up context resources ONLY if we created it
|
|
184
|
+
if should_clean_context:
|
|
183
185
|
exec_context.cleanup()
|
|
184
186
|
# Detach the context and end the span
|
|
185
187
|
# Only detach if we successfully attached (span was recording)
|
qtype/interpreter/types.py
CHANGED
|
@@ -292,6 +292,10 @@ class FlowMessage(BaseModel):
|
|
|
292
292
|
This object is the primary data structure passed between StepExecutors.
|
|
293
293
|
"""
|
|
294
294
|
|
|
295
|
+
model_config = ConfigDict(
|
|
296
|
+
frozen=True
|
|
297
|
+
) # Enforces immutability at the model level
|
|
298
|
+
|
|
295
299
|
session: Session
|
|
296
300
|
variables: Dict[str, Any] = Field(
|
|
297
301
|
default_factory=dict,
|
|
@@ -303,21 +307,25 @@ class FlowMessage(BaseModel):
|
|
|
303
307
|
"""Checks if this state has encountered an error."""
|
|
304
308
|
return self.error is not None
|
|
305
309
|
|
|
306
|
-
def
|
|
307
|
-
"""
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
310
|
+
def copy_with_error(self, step_id: str, exc: Exception) -> "FlowMessage":
|
|
311
|
+
"""Returns a copy of this state marked as failed."""
|
|
312
|
+
return self.model_copy(
|
|
313
|
+
update={
|
|
314
|
+
"error": StepError(
|
|
315
|
+
step_id=step_id,
|
|
316
|
+
error_message=str(exc),
|
|
317
|
+
exception_type=type(exc).__name__,
|
|
318
|
+
)
|
|
319
|
+
}
|
|
320
|
+
)
|
|
314
321
|
|
|
315
322
|
# It's useful to have copy-on-write style helpers
|
|
316
323
|
def copy_with_variables(
|
|
317
324
|
self, new_variables: dict[str, Any]
|
|
318
325
|
) -> "FlowMessage":
|
|
319
|
-
|
|
320
|
-
|
|
326
|
+
new_vars = self.variables.copy()
|
|
327
|
+
new_vars.update(new_variables)
|
|
328
|
+
new_state = self.model_copy(update={"variables": new_vars})
|
|
321
329
|
return new_state
|
|
322
330
|
|
|
323
331
|
|
qtype/interpreter/typing.py
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import uuid
|
|
4
|
-
from typing import Any, Type
|
|
4
|
+
from typing import Any, Type, get_origin
|
|
5
5
|
|
|
6
|
-
from pydantic import BaseModel, Field, create_model
|
|
6
|
+
from pydantic import BaseModel, Field, TypeAdapter, create_model
|
|
7
7
|
|
|
8
|
-
from qtype.dsl.model import PrimitiveTypeEnum
|
|
8
|
+
from qtype.dsl.model import ListType, PrimitiveTypeEnum
|
|
9
|
+
from qtype.dsl.model import Variable as DSLVariable
|
|
9
10
|
from qtype.dsl.types import PRIMITIVE_TO_PYTHON_TYPE
|
|
10
11
|
from qtype.interpreter.types import FlowMessage, Session
|
|
11
12
|
from qtype.semantic.model import Flow, Variable
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
def _get_variable_type(var:
|
|
15
|
+
def _get_variable_type(var: DSLVariable) -> tuple[Type, dict[str, Any]]:
|
|
15
16
|
"""Get the Python type and metadata for a variable.
|
|
16
17
|
|
|
17
18
|
Returns:
|
|
@@ -23,6 +24,13 @@ def _get_variable_type(var: Variable) -> tuple[Type, dict[str, Any]]:
|
|
|
23
24
|
if isinstance(var.type, PrimitiveTypeEnum):
|
|
24
25
|
python_type = PRIMITIVE_TO_PYTHON_TYPE.get(var.type, str)
|
|
25
26
|
field_metadata["qtype_type"] = var.type.value
|
|
27
|
+
elif isinstance(var.type, ListType):
|
|
28
|
+
python_type = list[
|
|
29
|
+
_get_variable_type(DSLVariable(id="", type=var.type.element_type))[
|
|
30
|
+
0
|
|
31
|
+
]
|
|
32
|
+
]
|
|
33
|
+
field_metadata["qtype_type"] = f"list[{var.type.element_type}]"
|
|
26
34
|
elif (
|
|
27
35
|
isinstance(var.type, type)
|
|
28
36
|
and issubclass(var.type, BaseModel)
|
|
@@ -40,6 +48,11 @@ def _fields_from_variables(variables: list[Variable]) -> dict:
|
|
|
40
48
|
fields = {}
|
|
41
49
|
for var in variables:
|
|
42
50
|
python_type, type_metadata = _get_variable_type(var)
|
|
51
|
+
|
|
52
|
+
# Add UI config to schema if present (OpenAPI x- extension pattern)
|
|
53
|
+
if var.ui is not None:
|
|
54
|
+
type_metadata["x-ui"] = var.ui
|
|
55
|
+
|
|
43
56
|
field_info = Field(
|
|
44
57
|
title=var.id,
|
|
45
58
|
json_schema_extra=type_metadata,
|
|
@@ -125,3 +138,39 @@ def flow_results_to_output_container(
|
|
|
125
138
|
outputs.append(output_instance.model_dump())
|
|
126
139
|
|
|
127
140
|
return output_container(outputs=outputs, errors=errors)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def instantiate_variable(variable: DSLVariable, value: Any) -> Any:
|
|
144
|
+
"""
|
|
145
|
+
Unified contract to ensure data matches its QType definition.
|
|
146
|
+
Handles CustomTypes, DomainTypes, and Primitives.
|
|
147
|
+
"""
|
|
148
|
+
target_type, _ = _get_variable_type(variable)
|
|
149
|
+
|
|
150
|
+
# 1. Handle the 'Parameterized Generic' Check (The isinstance fix)
|
|
151
|
+
# We check if target_type is a generic (like list[T]) vs a simple class.
|
|
152
|
+
origin = get_origin(target_type)
|
|
153
|
+
|
|
154
|
+
if origin is None:
|
|
155
|
+
# It's a simple type (int, RAGChunk, etc.)
|
|
156
|
+
if isinstance(value, target_type):
|
|
157
|
+
return value
|
|
158
|
+
else:
|
|
159
|
+
# It's a generic (list[str], etc.).
|
|
160
|
+
# We skip the identity check and let TypeAdapter handle it.
|
|
161
|
+
pass
|
|
162
|
+
|
|
163
|
+
# 2. Handle Pydantic Models (Custom/Domain Types)
|
|
164
|
+
if hasattr(target_type, "model_validate"):
|
|
165
|
+
return target_type.model_validate(value)
|
|
166
|
+
|
|
167
|
+
# 3. Handle Primitives & Complex Python Types (List, Optional, Union)
|
|
168
|
+
try:
|
|
169
|
+
# TypeAdapter is the "V2 way" to validate things that aren't
|
|
170
|
+
# full Pydantic models (like List[int] or Optional[str])
|
|
171
|
+
return TypeAdapter(target_type).validate_python(value)
|
|
172
|
+
except Exception:
|
|
173
|
+
# Fallback to your original manual cast if TypeAdapter is overkill
|
|
174
|
+
if isinstance(target_type, type):
|
|
175
|
+
return target_type(value)
|
|
176
|
+
raise ValueError(f"Unsupported target type: {target_type}")
|
qtype/semantic/checker.py
CHANGED
|
@@ -11,6 +11,8 @@ from qtype.semantic.model import (
|
|
|
11
11
|
Agent,
|
|
12
12
|
Application,
|
|
13
13
|
BedrockReranker,
|
|
14
|
+
Collect,
|
|
15
|
+
Construct,
|
|
14
16
|
Decoder,
|
|
15
17
|
DocToTextConverter,
|
|
16
18
|
DocumentEmbedder,
|
|
@@ -18,6 +20,7 @@ from qtype.semantic.model import (
|
|
|
18
20
|
DocumentSource,
|
|
19
21
|
DocumentSplitter,
|
|
20
22
|
Echo,
|
|
23
|
+
Explode,
|
|
21
24
|
FieldExtractor,
|
|
22
25
|
Flow,
|
|
23
26
|
IndexUpsert,
|
|
@@ -248,6 +251,83 @@ def _validate_decoder(step: Decoder) -> None:
|
|
|
248
251
|
_validate_min_output_count(step, 1)
|
|
249
252
|
|
|
250
253
|
|
|
254
|
+
def _validate_explode(step: Explode) -> None:
|
|
255
|
+
"""Validate Explode step has exactly one input of type list[T] and one output of type T."""
|
|
256
|
+
_validate_exact_input_count(step, 1)
|
|
257
|
+
_validate_exact_output_count(step, 1)
|
|
258
|
+
|
|
259
|
+
input_type = step.inputs[0].type
|
|
260
|
+
output_type = step.outputs[0].type
|
|
261
|
+
|
|
262
|
+
if not isinstance(input_type, ListType):
|
|
263
|
+
raise QTypeSemanticError(
|
|
264
|
+
(
|
|
265
|
+
f"Explode step '{step.id}' input must be of type 'list[T]', "
|
|
266
|
+
f"found '{input_type}'."
|
|
267
|
+
)
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
if input_type.element_type != output_type:
|
|
271
|
+
raise QTypeSemanticError(
|
|
272
|
+
(
|
|
273
|
+
f"Explode step '{step.id}' output type must match the element "
|
|
274
|
+
f"type of the input list. Input element type: "
|
|
275
|
+
f"'{input_type.element_type}', Output type: '{output_type}'."
|
|
276
|
+
)
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def _validate_construct(step: Construct) -> None:
|
|
281
|
+
"""Validate Construct step has at least one input, exactly one output, and that the
|
|
282
|
+
output type is inherited from a pydantic base class (i.e., it is a Custom type or a Domain type)
|
|
283
|
+
"""
|
|
284
|
+
_validate_exact_output_count(step, 1)
|
|
285
|
+
|
|
286
|
+
if len(step.inputs) < 1:
|
|
287
|
+
raise QTypeSemanticError(
|
|
288
|
+
(
|
|
289
|
+
f"Construct step '{step.id}' must have at least one input variable."
|
|
290
|
+
)
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
output_type = step.outputs[0].type
|
|
294
|
+
if not (
|
|
295
|
+
isinstance(output_type, type) and issubclass(output_type, BaseModel)
|
|
296
|
+
):
|
|
297
|
+
raise QTypeSemanticError(
|
|
298
|
+
(
|
|
299
|
+
f"Construct step '{step.id}' output type must be a Pydantic "
|
|
300
|
+
f"BaseModel (Custom type or Domain type), found '{output_type}'."
|
|
301
|
+
)
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def _validate_collect(step: Collect) -> None:
|
|
306
|
+
"""Validate Collect step has exactly one input of type T and one output of type list[T]."""
|
|
307
|
+
_validate_exact_input_count(step, 1)
|
|
308
|
+
_validate_exact_output_count(step, 1)
|
|
309
|
+
|
|
310
|
+
input_type = step.inputs[0].type
|
|
311
|
+
output_type = step.outputs[0].type
|
|
312
|
+
|
|
313
|
+
if not isinstance(output_type, ListType):
|
|
314
|
+
raise QTypeSemanticError(
|
|
315
|
+
(
|
|
316
|
+
f"Collect step '{step.id}' output must be of type 'list[T]', "
|
|
317
|
+
f"found '{output_type}'."
|
|
318
|
+
)
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
if output_type.element_type != input_type:
|
|
322
|
+
raise QTypeSemanticError(
|
|
323
|
+
(
|
|
324
|
+
f"Collect step '{step.id}' output element type must match the "
|
|
325
|
+
f"input type. Input type: '{input_type}', Output element type: "
|
|
326
|
+
f"'{output_type.element_type}'."
|
|
327
|
+
)
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
|
|
251
331
|
def _validate_echo(step: Echo) -> None:
|
|
252
332
|
"""
|
|
253
333
|
Validate Echo step has matching input and output variable IDs.
|
|
@@ -588,6 +668,8 @@ _VALIDATORS = {
|
|
|
588
668
|
Application: _validate_application,
|
|
589
669
|
AWSAuthProvider: _validate_aws_auth,
|
|
590
670
|
BedrockReranker: _validate_bedrock_reranker,
|
|
671
|
+
Collect: _validate_collect,
|
|
672
|
+
Construct: _validate_construct,
|
|
591
673
|
Decoder: _validate_decoder,
|
|
592
674
|
DocToTextConverter: _validate_doc_to_text_converter,
|
|
593
675
|
DocumentEmbedder: _validate_document_embedder,
|
|
@@ -595,6 +677,7 @@ _VALIDATORS = {
|
|
|
595
677
|
DocumentSource: _validate_document_source,
|
|
596
678
|
DocumentSplitter: _validate_document_splitter,
|
|
597
679
|
Echo: _validate_echo,
|
|
680
|
+
Explode: _validate_explode,
|
|
598
681
|
FieldExtractor: _validate_field_extractor,
|
|
599
682
|
Flow: _validate_flow,
|
|
600
683
|
IndexUpsert: _validate_index_upsert,
|
qtype/semantic/generate.py
CHANGED
qtype/semantic/model.py
CHANGED
|
@@ -32,7 +32,6 @@ from qtype.dsl.model import ( # noqa: F401
|
|
|
32
32
|
DecoderFormat,
|
|
33
33
|
ListType,
|
|
34
34
|
PrimitiveTypeEnum,
|
|
35
|
-
StepCardinality,
|
|
36
35
|
ToolParameter,
|
|
37
36
|
)
|
|
38
37
|
from qtype.dsl.model import Variable as DSLVariable # noqa: F401
|
|
@@ -95,10 +94,6 @@ class Step(CachedStepMixin, BaseModel):
|
|
|
95
94
|
|
|
96
95
|
id: str = Field(..., description="Unique ID of this component.")
|
|
97
96
|
type: str = Field(..., description="Type of the step component.")
|
|
98
|
-
cardinality: StepCardinality = Field(
|
|
99
|
-
StepCardinality.one,
|
|
100
|
-
description="Does this step emit 1 (one) or 0...N (many) instances of the outputs?",
|
|
101
|
-
)
|
|
102
97
|
inputs: list[Variable] = Field(
|
|
103
98
|
default_factory=list,
|
|
104
99
|
description="References to the variables required by this step.",
|
|
@@ -457,13 +452,31 @@ class Aggregate(Step):
|
|
|
457
452
|
"""
|
|
458
453
|
|
|
459
454
|
type: Literal["Aggregate"] = Field("Aggregate")
|
|
460
|
-
cardinality: Literal[StepCardinality.one] = Field(StepCardinality.one)
|
|
461
455
|
outputs: list[Variable] = Field(
|
|
462
456
|
default_factory=list,
|
|
463
457
|
description="References to the variables for the output. There should be one and only one output with type AggregateStats",
|
|
464
458
|
)
|
|
465
459
|
|
|
466
460
|
|
|
461
|
+
class Collect(Step, BatchableStepMixin):
|
|
462
|
+
"""A step that collects all inputs and creates a single list to return."""
|
|
463
|
+
|
|
464
|
+
type: Literal["Collect"] = Field("Collect")
|
|
465
|
+
batch_config: BatchConfig = Field(
|
|
466
|
+
default_factory=partial(BatchConfig, batch_size=9223372036854775807),
|
|
467
|
+
description="Configuration for processing the input stream in batches. If omitted, the step processes items one by one.",
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
class Construct(Step):
|
|
472
|
+
"""A step that converts variables into an instance of a Custom or Domain Type"""
|
|
473
|
+
|
|
474
|
+
type: Literal["Construct"] = Field("Construct")
|
|
475
|
+
field_mapping: dict[str, str] = Field(
|
|
476
|
+
..., description="Mapping of type inputs to variable names, if needed."
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
|
|
467
480
|
class Decoder(Step):
|
|
468
481
|
"""Defines a step that decodes string data into structured outputs.
|
|
469
482
|
|
|
@@ -490,10 +503,6 @@ class DocumentEmbedder(Step, ConcurrentStepMixin):
|
|
|
490
503
|
"""Embeds document chunks using a specified embedding model."""
|
|
491
504
|
|
|
492
505
|
type: Literal["DocumentEmbedder"] = Field("DocumentEmbedder")
|
|
493
|
-
cardinality: Literal[StepCardinality.many] = Field(
|
|
494
|
-
StepCardinality.many,
|
|
495
|
-
description="Consumes one chunk and emits one embedded chunk.",
|
|
496
|
-
)
|
|
497
506
|
model: EmbeddingModel = Field(
|
|
498
507
|
..., description="Embedding model to use for vectorization."
|
|
499
508
|
)
|
|
@@ -503,10 +512,6 @@ class DocumentSplitter(Step, ConcurrentStepMixin):
|
|
|
503
512
|
"""Configuration for chunking/splitting documents into embeddable nodes/chunks."""
|
|
504
513
|
|
|
505
514
|
type: Literal["DocumentSplitter"] = Field("DocumentSplitter")
|
|
506
|
-
cardinality: Literal[StepCardinality.many] = Field(
|
|
507
|
-
StepCardinality.many,
|
|
508
|
-
description="Consumes one document and emits 0...N nodes/chunks.",
|
|
509
|
-
)
|
|
510
515
|
splitter_name: str = Field(
|
|
511
516
|
"SentenceSplitter",
|
|
512
517
|
description="Name of the LlamaIndex TextSplitter class.",
|
|
@@ -532,6 +537,12 @@ class Echo(Step):
|
|
|
532
537
|
type: Literal["Echo"] = Field("Echo")
|
|
533
538
|
|
|
534
539
|
|
|
540
|
+
class Explode(Step):
|
|
541
|
+
"""A step that takes a list input and produces multiple outputs, one per item in the list."""
|
|
542
|
+
|
|
543
|
+
type: Literal["Explode"] = Field("Explode")
|
|
544
|
+
|
|
545
|
+
|
|
535
546
|
class FieldExtractor(Step):
|
|
536
547
|
"""Extracts specific fields from input data using JSONPath expressions.
|
|
537
548
|
|
|
@@ -657,10 +668,6 @@ class Source(Step):
|
|
|
657
668
|
"""Base class for data sources"""
|
|
658
669
|
|
|
659
670
|
id: str = Field(..., description="Unique ID of the data source.")
|
|
660
|
-
cardinality: Literal[StepCardinality.many] = Field(
|
|
661
|
-
StepCardinality.many,
|
|
662
|
-
description="Sources always emit 0...N instances of the outputs.",
|
|
663
|
-
)
|
|
664
671
|
|
|
665
672
|
|
|
666
673
|
class Writer(Step, BatchableStepMixin):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qtype
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
4
4
|
Summary: DSL for Generative AI Prototyping
|
|
5
5
|
Author-email: Lou Kratz <lou.kratz+qtype@bazaarvoice.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -9,7 +9,7 @@ Requires-Python: >=3.10
|
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Requires-Dist: jsonschema>=4.24.0
|
|
12
|
-
Requires-Dist: pydantic>=2.
|
|
12
|
+
Requires-Dist: pydantic>=2.12.4
|
|
13
13
|
Requires-Dist: pyyaml>=6.0.2
|
|
14
14
|
Requires-Dist: python-dotenv>=1.0.0
|
|
15
15
|
Requires-Dist: openai>=1.93.0
|
|
@@ -12,7 +12,8 @@ qtype/application/converters/types.py,sha256=OsJQ2fmgQm5NaxgS9cvHER9anfv3qttbt7c
|
|
|
12
12
|
qtype/base/__init__.py,sha256=4jwcB8cDHzDNF3NBv8WqHNk3sDZDNvUFNjx2CKZ-pyY,283
|
|
13
13
|
qtype/base/exceptions.py,sha256=NR6-p6FnIabFPid9xIUTTeNhCYoIw8sbxEzaWQ11a4o,1155
|
|
14
14
|
qtype/base/logging.py,sha256=eqStjILlmhNryYRqUiyTdDHoUoiLKSY8J0GevvzvTKQ,1075
|
|
15
|
-
qtype/base/types.py,sha256=
|
|
15
|
+
qtype/base/types.py,sha256=Z-x9ytcmPPCmtkzu_JAn9wBdBiaUKqPpmVzgUIB_SaM,6676
|
|
16
|
+
qtype/base/ui_shapes.py,sha256=FkziyJ8VKqimpDepTK6tlZ47HQzNwJUeKARAM2qOYKo,921
|
|
16
17
|
qtype/commands/__init__.py,sha256=Qo4M07zm5I63r8STxDjvt5fhP1jygdXTsExNGELkefc,257
|
|
17
18
|
qtype/commands/convert.py,sha256=wh2-MSBlnMU5peAzVeQcGqqFzQbeCuL5WC5-EDZ-TFM,4636
|
|
18
19
|
qtype/commands/generate.py,sha256=OQEkuh3dTVu6ZUNAuH_HkU-9YktYySL0qjTdrz28FY8,7285
|
|
@@ -25,56 +26,59 @@ qtype/dsl/custom_types.py,sha256=N3qswimv0foH40YDubHaTZ3HYF9RUbZ2x5eQ4i798Ko,290
|
|
|
25
26
|
qtype/dsl/domain_types.py,sha256=-pX74DKwrRanoXBxYqAdN_f44ike6ssRV3tZ20R2PhQ,4319
|
|
26
27
|
qtype/dsl/linker.py,sha256=c7PPTULy7_z_9u_qeseIaomR_B8kBa9YzOhQpjeGaSM,12975
|
|
27
28
|
qtype/dsl/loader.py,sha256=mht0BqfmyTNHIEDaF3iTEmYQLJBP5GIZULwexxw9Dpg,9771
|
|
28
|
-
qtype/dsl/model.py,sha256=
|
|
29
|
+
qtype/dsl/model.py,sha256=V0Tap3blGOk56F8ARM_qcfMWIyeKwuWAXmyD6xgtw-Y,41589
|
|
29
30
|
qtype/dsl/parser.py,sha256=Ww32bLQ2vGOObsA-vWjaMh4TOKRwEA7FAt9U6wjKZkw,5490
|
|
30
31
|
qtype/dsl/types.py,sha256=k6cgThA287bZ_pvTKQvxWhatcYCPNne8zpqOYOvLvOg,1687
|
|
31
32
|
qtype/interpreter/__init__.py,sha256=IaRF90JLFbsTLKz9LTOMI_Pz4xwVaEyXPNaXV7sLou8,43
|
|
32
33
|
qtype/interpreter/api.py,sha256=V7hjsmDhe1IwbcwdM5bnPGBiwH3TtlMLjUJdGJumCdA,4193
|
|
33
|
-
qtype/interpreter/conversions.py,sha256=
|
|
34
|
+
qtype/interpreter/conversions.py,sha256=ZSlFCRsfNLd-j2hBhGK9aMdJN_XCHFUrf-Qjrj9YfRQ,22083
|
|
34
35
|
qtype/interpreter/converters.py,sha256=gWyfizl7d-DT6jJ2aOrneUcZcwB-LdMDEvl-VT0-mLQ,2348
|
|
35
36
|
qtype/interpreter/endpoints.py,sha256=un4iCYCk86lYKpTDFdzlByvebdctNwRF3n4oD4ZwpTw,11946
|
|
36
|
-
qtype/interpreter/flow.py,sha256=
|
|
37
|
+
qtype/interpreter/flow.py,sha256=cer1z8qcG9rVkUm3Ly0zBKekZIiilQVoDh8qrr-m9bs,6703
|
|
37
38
|
qtype/interpreter/logging_progress.py,sha256=RmyNXdbpPZ7ye8cbSab0Tw10x3T38U3S8rj2bOTfbso,1848
|
|
38
39
|
qtype/interpreter/metadata_api.py,sha256=LfJjt9atsgiAra6aVBXLoJrPa06_CBUagYysT556nt8,3267
|
|
39
40
|
qtype/interpreter/resource_cache.py,sha256=K0kzpm223COWk7FN9qyOvNOEoOcABR4yLeADL9ekE_o,1188
|
|
40
41
|
qtype/interpreter/rich_progress.py,sha256=J7TokOIqIUVWJZCfGEexQCwvvj6b1SjRtKThk2DU0CA,6761
|
|
41
42
|
qtype/interpreter/telemetry.py,sha256=Hcwd9sMW55LejgOIpPwjkWsmTvB2vnpSr4TshTAKljk,4901
|
|
42
|
-
qtype/interpreter/types.py,sha256=
|
|
43
|
-
qtype/interpreter/typing.py,sha256=
|
|
43
|
+
qtype/interpreter/types.py,sha256=mortEGCZ4N-n48FApmN7_t8PWJSwAxl9M9zPOrZECeU,10243
|
|
44
|
+
qtype/interpreter/typing.py,sha256=Py--NgJxbwZS-Jtxa8rNBvtfduzmhFtutnxJ2_bR7pU,5790
|
|
44
45
|
qtype/interpreter/auth/__init__.py,sha256=L98AxaSizb6LMdXEr8FGe9MBtPBnfCeWxjI0oi7sg_o,62
|
|
45
46
|
qtype/interpreter/auth/aws.py,sha256=eMXyEBqzv7I243fS-A1zHPQkN--yPFEh1Hxp4rxmyEs,8154
|
|
46
47
|
qtype/interpreter/auth/cache.py,sha256=uVyJ_jkbprRdlvbnm1DVIaYyTDLEsPXvi3xjuRneH2k,1825
|
|
47
48
|
qtype/interpreter/auth/generic.py,sha256=WHXu3SxWzxJn_bv6R20Aod84Vwe73xTYHx754dY1MSg,6178
|
|
48
|
-
qtype/interpreter/base/base_step_executor.py,sha256=
|
|
49
|
+
qtype/interpreter/base/base_step_executor.py,sha256=U6DswFvDrIURrLP8xVwP-fxBKW6u9cdToLz_iqC64sY,16486
|
|
49
50
|
qtype/interpreter/base/batch_step_executor.py,sha256=g5_yPd5VTy_slW5ZXyamgFyTRd0CoaeVfDHj8x4PvUk,5906
|
|
50
51
|
qtype/interpreter/base/exceptions.py,sha256=7CIexzDfIjvAA0c6qwg4jsDcTQM1pKQLj6szxcqil_c,1586
|
|
51
52
|
qtype/interpreter/base/executor_context.py,sha256=qDMb7GJebCw3E6oMiCSpu0-aRq-l6MPx6yPLwM2quOs,3561
|
|
52
|
-
qtype/interpreter/base/factory.py,sha256=
|
|
53
|
+
qtype/interpreter/base/factory.py,sha256=ZzhtFS7wgBbskQJWCmphZ9lYztU77mv4pxfihypacQg,3812
|
|
53
54
|
qtype/interpreter/base/progress_tracker.py,sha256=zHtTp0JGrn1M3wNEEVfkwQmuHD-WKXV7tv4fDdHv1xs,3488
|
|
54
55
|
qtype/interpreter/base/secrets.py,sha256=74NoU0Fx96vva6LGWXk7EkvFWD4uZEk12NjWrGHWZTc,11241
|
|
55
|
-
qtype/interpreter/base/step_cache.py,sha256=
|
|
56
|
+
qtype/interpreter/base/step_cache.py,sha256=kP2xXFycEzTEC8H7glhfptd3FOQ1xITMjoctzX3bqc0,2435
|
|
56
57
|
qtype/interpreter/base/stream_emitter.py,sha256=8l5bCFTjMA3Takjh51QdWw8ERb7_GamHVoU-x6xkG5I,13828
|
|
57
|
-
qtype/interpreter/executors/agent_executor.py,sha256=
|
|
58
|
+
qtype/interpreter/executors/agent_executor.py,sha256=EHGBFzWtq6lka-ZHIrXzcYzesJtYDNYpsEib6swKkn8,8364
|
|
58
59
|
qtype/interpreter/executors/aggregate_executor.py,sha256=Z3NJekpeo7aqqvOcXQqb6d6t9g4UB1r3N1lSV9EwZq4,3495
|
|
59
|
-
qtype/interpreter/executors/bedrock_reranker_executor.py,sha256=
|
|
60
|
-
qtype/interpreter/executors/
|
|
61
|
-
qtype/interpreter/executors/
|
|
62
|
-
qtype/interpreter/executors/
|
|
63
|
-
qtype/interpreter/executors/
|
|
64
|
-
qtype/interpreter/executors/
|
|
65
|
-
qtype/interpreter/executors/
|
|
66
|
-
qtype/interpreter/executors/
|
|
67
|
-
qtype/interpreter/executors/
|
|
60
|
+
qtype/interpreter/executors/bedrock_reranker_executor.py,sha256=FM0O7bpeDj_k-XjTnilQLoZNEgqXJBS5-RBM9ecs8DE,7140
|
|
61
|
+
qtype/interpreter/executors/collect_executor.py,sha256=qUxx72YRtw3Oca7RyQoa5Hl-SyMcWDWl3FcZa0vEKTU,2518
|
|
62
|
+
qtype/interpreter/executors/construct_executor.py,sha256=wEevRmnvVcMjXh2oikC0S2ipnU3DjI-IgOY3t7SXG00,2479
|
|
63
|
+
qtype/interpreter/executors/decoder_executor.py,sha256=zz4jZQwLRYM9t3p1jGWmEIvd3libaudSTvPsqqiOw68,5596
|
|
64
|
+
qtype/interpreter/executors/doc_to_text_executor.py,sha256=DYRct0elL-k5zWiqZVYrxCZqZJgg2lkyy0vTKuI4d2I,3790
|
|
65
|
+
qtype/interpreter/executors/document_embedder_executor.py,sha256=J2fZGll8mmBjRGKdqmIQ_Yhao6YcH5mAmbGtIxykc0k,4075
|
|
66
|
+
qtype/interpreter/executors/document_search_executor.py,sha256=XSo2JLmKGBZOlTk2E_OqlQUlf7ecF2hTsmqpVGi7Ti0,4037
|
|
67
|
+
qtype/interpreter/executors/document_source_executor.py,sha256=DuE0gzT6oBPo9wenZZFpjWxCpyhW2yUTipda_xl8Lqc,4233
|
|
68
|
+
qtype/interpreter/executors/document_splitter_executor.py,sha256=vHIjr-Mg5V7IW33qatgD8aKPOCPKRzb6OhpC88HGEbQ,3868
|
|
69
|
+
qtype/interpreter/executors/echo_executor.py,sha256=MzU1SHnbPLvN6iEZWKjIhtd5OFVszmhgokQX-2sGE1c,2180
|
|
70
|
+
qtype/interpreter/executors/explode_executor.py,sha256=GBE2SZjzWXfkvJzNBjap-I7Fuv7Vhu9YXUgsi7kLOeU,1588
|
|
71
|
+
qtype/interpreter/executors/field_extractor_executor.py,sha256=r2IJuxfosHuSC2DKuSohCu6Gd8MrKUKX2kNWPCDO1Gw,5782
|
|
68
72
|
qtype/interpreter/executors/file_source_executor.py,sha256=OUT_zJrYN3iFMUgLECde93C4rv8PthcQsuJ--CJvEsI,3605
|
|
69
|
-
qtype/interpreter/executors/file_writer_executor.py,sha256=
|
|
70
|
-
qtype/interpreter/executors/index_upsert_executor.py,sha256=
|
|
71
|
-
qtype/interpreter/executors/invoke_embedding_executor.py,sha256=
|
|
73
|
+
qtype/interpreter/executors/file_writer_executor.py,sha256=u3jKY-K9BsZ5juSksyjyF_6HDxI2YRT8Ry4V4YcT6L8,4260
|
|
74
|
+
qtype/interpreter/executors/index_upsert_executor.py,sha256=DF11uHpfYMDOjcowoxYW_QhpsCdOuC7dbcYefcq3Heg,8516
|
|
75
|
+
qtype/interpreter/executors/invoke_embedding_executor.py,sha256=vXja0hTReiVs8q47K-bXiVYxhdQwUsKlLGMG4GGc3MA,3820
|
|
72
76
|
qtype/interpreter/executors/invoke_flow_executor.py,sha256=U30cYM3F_zy1_2CD1Dde59xyZD0rDa5W46lST1hxF6s,1682
|
|
73
|
-
qtype/interpreter/executors/invoke_tool_executor.py,sha256=
|
|
74
|
-
qtype/interpreter/executors/llm_inference_executor.py,sha256=
|
|
75
|
-
qtype/interpreter/executors/prompt_template_executor.py,sha256=
|
|
76
|
-
qtype/interpreter/executors/sql_source_executor.py,sha256
|
|
77
|
-
qtype/interpreter/executors/vector_search_executor.py,sha256=
|
|
77
|
+
qtype/interpreter/executors/invoke_tool_executor.py,sha256=6iitiXylARNnz9kr5Bvcni-KGXk1L4iuYFYQfbqH3Mc,12772
|
|
78
|
+
qtype/interpreter/executors/llm_inference_executor.py,sha256=bQu1Qb0hzhkiBBeU4SXYVPTjwgic3r_gVcyegZun2tE,9579
|
|
79
|
+
qtype/interpreter/executors/prompt_template_executor.py,sha256=s3GuLv1iYC0SH_h1V-g8Xm5s5afzQrDN5z4LlIiZ6eY,2686
|
|
80
|
+
qtype/interpreter/executors/sql_source_executor.py,sha256=VO-O3XxTquwps6KMMy0VL5nk_O45xNAIdXXQh0wirKY,3918
|
|
81
|
+
qtype/interpreter/executors/vector_search_executor.py,sha256=X6fWIrQ7TT_sm9SamNBtvY1ETyAI_7pV0Hs7IM2TMd4,3175
|
|
78
82
|
qtype/interpreter/stream/chat/__init__.py,sha256=evNfJJp3VUiTgip8___vBryAZubS-cij-8YYAjOJXX8,401
|
|
79
83
|
qtype/interpreter/stream/chat/converter.py,sha256=0kAYtX_QNDZHJbzFHJGTHYLlKbl79hDkmZuFECG7FSQ,13623
|
|
80
84
|
qtype/interpreter/stream/chat/file_conversions.py,sha256=klSsXjATfSoOzKEjAiabGRXKErIHxP6-bVWbNM3EM4E,1751
|
|
@@ -123,15 +127,15 @@ qtype/interpreter/ui/_next/static/media/9610d9e46709d722-s.woff2,sha256=N08hXnJf
|
|
|
123
127
|
qtype/interpreter/ui/_next/static/media/ba015fad6dcf6784-s.woff2,sha256=92BKU6ACUPZttLR91EMnzipD9u3shQ1SF7uAI4gZ790,15292
|
|
124
128
|
qtype/semantic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
125
129
|
qtype/semantic/base_types.py,sha256=wfUlT0gV3_Mk1xLLI64SSXCB9GFmn29yz5adTaHrsOI,1540
|
|
126
|
-
qtype/semantic/checker.py,sha256=
|
|
127
|
-
qtype/semantic/generate.py,sha256=
|
|
130
|
+
qtype/semantic/checker.py,sha256=XESGDrHMAwAYgWQ3vE7dyIa6ejGk66opdkDGN1XJXgQ,25036
|
|
131
|
+
qtype/semantic/generate.py,sha256=asSm52LvQkkJPJfPnf41O3C7fgWTDc48lAlaJ4971HA,21083
|
|
128
132
|
qtype/semantic/loader.py,sha256=QRhTc_AJfsWSMn8ThaW60GmIGjFMN-3bBUy4pktFjz4,3041
|
|
129
|
-
qtype/semantic/model.py,sha256=
|
|
133
|
+
qtype/semantic/model.py,sha256=eUPmdYgtRxx2U3zcC4thjh52-vHuNQAKS10hCRGjr14,28724
|
|
130
134
|
qtype/semantic/resolver.py,sha256=bWPCSB8KJpVqN_n41U_r-qzUiT8vAMBOD3pOGmxL6TY,4618
|
|
131
135
|
qtype/semantic/visualize.py,sha256=thjrZcfQuZJWrZ9EMAPhAa2kNikR5rLIJrfcD3hJ8XY,17426
|
|
132
|
-
qtype-0.1.
|
|
133
|
-
qtype-0.1.
|
|
134
|
-
qtype-0.1.
|
|
135
|
-
qtype-0.1.
|
|
136
|
-
qtype-0.1.
|
|
137
|
-
qtype-0.1.
|
|
136
|
+
qtype-0.1.8.dist-info/licenses/LICENSE,sha256=1KA5EgYBSR0O6nCH2HEvk6Di53YKJ9r_VCR7G8G8qAY,11341
|
|
137
|
+
qtype-0.1.8.dist-info/METADATA,sha256=a7jj7rU0dNjXQTzozkaXhBogxzx80WjJcjIdjVHicr8,5657
|
|
138
|
+
qtype-0.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
139
|
+
qtype-0.1.8.dist-info/entry_points.txt,sha256=5y4vj8RLvgl2tXSj-Hm7v5-Tn3kP4-UonjNoN-mfaQE,41
|
|
140
|
+
qtype-0.1.8.dist-info/top_level.txt,sha256=ONroH5B0mZ51jr7NSWCK0weFwwCO7wBLmyVS1YqNU14,6
|
|
141
|
+
qtype-0.1.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|