qtype 0.1.0__py3-none-any.whl → 0.1.2__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/application/facade.py +16 -17
- qtype/cli.py +5 -1
- qtype/commands/generate.py +1 -1
- qtype/commands/run.py +28 -5
- qtype/dsl/domain_types.py +24 -3
- qtype/dsl/model.py +56 -3
- qtype/interpreter/base/base_step_executor.py +8 -1
- qtype/interpreter/base/executor_context.py +18 -1
- qtype/interpreter/base/factory.py +33 -66
- qtype/interpreter/base/progress_tracker.py +35 -0
- qtype/interpreter/base/step_cache.py +3 -2
- qtype/interpreter/conversions.py +34 -19
- qtype/interpreter/converters.py +19 -13
- qtype/interpreter/executors/bedrock_reranker_executor.py +195 -0
- qtype/interpreter/executors/document_embedder_executor.py +36 -4
- qtype/interpreter/executors/document_search_executor.py +37 -46
- qtype/interpreter/executors/document_splitter_executor.py +1 -1
- qtype/interpreter/executors/field_extractor_executor.py +10 -5
- qtype/interpreter/executors/index_upsert_executor.py +115 -111
- qtype/interpreter/executors/invoke_embedding_executor.py +2 -2
- qtype/interpreter/executors/invoke_tool_executor.py +6 -1
- qtype/interpreter/flow.py +47 -32
- qtype/interpreter/rich_progress.py +225 -0
- qtype/interpreter/types.py +2 -0
- qtype/semantic/checker.py +79 -19
- qtype/semantic/model.py +43 -3
- qtype/semantic/resolver.py +4 -2
- {qtype-0.1.0.dist-info → qtype-0.1.2.dist-info}/METADATA +12 -11
- {qtype-0.1.0.dist-info → qtype-0.1.2.dist-info}/RECORD +33 -31
- {qtype-0.1.0.dist-info → qtype-0.1.2.dist-info}/WHEEL +0 -0
- {qtype-0.1.0.dist-info → qtype-0.1.2.dist-info}/entry_points.txt +0 -0
- {qtype-0.1.0.dist-info → qtype-0.1.2.dist-info}/licenses/LICENSE +0 -0
- {qtype-0.1.0.dist-info → qtype-0.1.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import threading
|
|
5
|
+
from collections import deque
|
|
6
|
+
from typing import Deque, Dict
|
|
7
|
+
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from rich.live import Live
|
|
10
|
+
from rich.panel import Panel
|
|
11
|
+
from rich.progress import (
|
|
12
|
+
Progress,
|
|
13
|
+
ProgressColumn,
|
|
14
|
+
TaskProgressColumn,
|
|
15
|
+
TextColumn,
|
|
16
|
+
TimeElapsedColumn,
|
|
17
|
+
TimeRemainingColumn,
|
|
18
|
+
)
|
|
19
|
+
from rich.text import Text
|
|
20
|
+
|
|
21
|
+
from qtype.interpreter.types import ProgressCallback
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class RateColumn(ProgressColumn):
|
|
27
|
+
"""Show processing speed as '123 msg/s' based on task.speed."""
|
|
28
|
+
|
|
29
|
+
def __init__(self, unit: str = "msg") -> None:
|
|
30
|
+
super().__init__()
|
|
31
|
+
self.unit = unit
|
|
32
|
+
|
|
33
|
+
def render(self, task) -> Text: # type: ignore[override]
|
|
34
|
+
speed = task.speed or 0.0
|
|
35
|
+
|
|
36
|
+
if speed <= 0:
|
|
37
|
+
return Text(f"- {self.unit}/s")
|
|
38
|
+
|
|
39
|
+
# Simple formatting similar-ish to tqdm
|
|
40
|
+
if speed < 1:
|
|
41
|
+
rate_str = f"{speed:.2f}"
|
|
42
|
+
elif speed < 100:
|
|
43
|
+
rate_str = f"{speed:4.1f}"
|
|
44
|
+
else:
|
|
45
|
+
rate_str = f"{speed:4.0f}"
|
|
46
|
+
|
|
47
|
+
return Text(f"{rate_str} {self.unit}/s")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class SparklineColumn(ProgressColumn):
|
|
51
|
+
"""Tiny throughput trend graph using block characters."""
|
|
52
|
+
|
|
53
|
+
def __init__(self, max_samples: int = 20) -> None:
|
|
54
|
+
super().__init__()
|
|
55
|
+
self.max_samples = max_samples
|
|
56
|
+
# Per-task speed history
|
|
57
|
+
self._history: Dict[int, Deque[float]] = {}
|
|
58
|
+
|
|
59
|
+
def render(self, task) -> Text: # type: ignore[override]
|
|
60
|
+
speed = task.speed or 0.0
|
|
61
|
+
|
|
62
|
+
history = self._history.get(task.id)
|
|
63
|
+
if history is None:
|
|
64
|
+
history = self._history[task.id] = deque(maxlen=self.max_samples)
|
|
65
|
+
|
|
66
|
+
history.append(speed)
|
|
67
|
+
|
|
68
|
+
if not history or all(v <= 0 for v in history):
|
|
69
|
+
return Text("")
|
|
70
|
+
|
|
71
|
+
min_s = min(history)
|
|
72
|
+
max_s = max(history)
|
|
73
|
+
rng = max(max_s - min_s, 1e-9)
|
|
74
|
+
|
|
75
|
+
blocks = "▁▂▃▄▅▆▇█"
|
|
76
|
+
n_blocks = len(blocks)
|
|
77
|
+
|
|
78
|
+
chars = []
|
|
79
|
+
for v in history:
|
|
80
|
+
idx = int((v - min_s) / rng * (n_blocks - 1))
|
|
81
|
+
chars.append(blocks[idx])
|
|
82
|
+
|
|
83
|
+
return Text("".join(chars))
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class RichProgressCallback(ProgressCallback):
|
|
87
|
+
"""Progress callback that uses Rich to display progress bars.
|
|
88
|
+
|
|
89
|
+
Displays a progress row for each step, updating in place.
|
|
90
|
+
Colors the step label based on error rate:
|
|
91
|
+
- Green: error rate <= 1%
|
|
92
|
+
- Yellow: 1% < error rate <= 5%
|
|
93
|
+
- Red: error rate > 5%
|
|
94
|
+
|
|
95
|
+
Attributes:
|
|
96
|
+
order: Optional list defining the order of steps progress rows.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
def __init__(
|
|
100
|
+
self,
|
|
101
|
+
order: list[str] | None = None,
|
|
102
|
+
) -> None:
|
|
103
|
+
super().__init__()
|
|
104
|
+
self.order = order or []
|
|
105
|
+
self._lock = threading.Lock()
|
|
106
|
+
self.console = Console()
|
|
107
|
+
|
|
108
|
+
# One shared Progress instance for all steps
|
|
109
|
+
# Columns: description | bar | % | rate | sparkline | ✔ | ✖ | elapsed | remaining
|
|
110
|
+
self.progress = Progress(
|
|
111
|
+
TextColumn("[progress.description]{task.description}"),
|
|
112
|
+
TaskProgressColumn(),
|
|
113
|
+
RateColumn(unit="msg"),
|
|
114
|
+
SparklineColumn(max_samples=20),
|
|
115
|
+
TextColumn("[green]✔[/green] {task.fields[succeeded]} succeeded"),
|
|
116
|
+
TextColumn("[red]✖[/red] {task.fields[errors]} errors"),
|
|
117
|
+
TextColumn("[cyan]⟳[/cyan] {task.fields[cache_hits]} hits"),
|
|
118
|
+
TextColumn(
|
|
119
|
+
"[magenta]✗[/magenta] {task.fields[cache_misses]} misses"
|
|
120
|
+
),
|
|
121
|
+
TimeElapsedColumn(),
|
|
122
|
+
TimeRemainingColumn(),
|
|
123
|
+
console=self.console,
|
|
124
|
+
expand=True,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# Wrap progress in a panel
|
|
128
|
+
self.panel = Panel(
|
|
129
|
+
self.progress,
|
|
130
|
+
title="[bold cyan]Flow Progress[/bold cyan]",
|
|
131
|
+
border_style="bright_blue",
|
|
132
|
+
padding=(1, 2),
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Live container for the panel
|
|
136
|
+
self.live = Live(
|
|
137
|
+
self.panel,
|
|
138
|
+
console=self.console,
|
|
139
|
+
refresh_per_second=10,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Map step_id -> Rich task id
|
|
143
|
+
self.tasks: Dict[str, int] = {}
|
|
144
|
+
self._started = False
|
|
145
|
+
|
|
146
|
+
# Pre-create tasks in the desired order if provided
|
|
147
|
+
for step_id in self.order:
|
|
148
|
+
task_id = self.progress.add_task(
|
|
149
|
+
f"Step {step_id}",
|
|
150
|
+
total=None, # we’ll update this once we know it
|
|
151
|
+
succeeded=0,
|
|
152
|
+
errors=0,
|
|
153
|
+
)
|
|
154
|
+
self.tasks[step_id] = task_id
|
|
155
|
+
|
|
156
|
+
def _ensure_started(self) -> None:
|
|
157
|
+
if not self._started:
|
|
158
|
+
self.live.start()
|
|
159
|
+
self._started = True
|
|
160
|
+
|
|
161
|
+
def __call__(
|
|
162
|
+
self,
|
|
163
|
+
step_id: str,
|
|
164
|
+
items_processed: int,
|
|
165
|
+
items_in_error: int,
|
|
166
|
+
items_succeeded: int,
|
|
167
|
+
total_items: int | None,
|
|
168
|
+
cache_hits: int | None = None,
|
|
169
|
+
cache_misses: int | None = None,
|
|
170
|
+
) -> None:
|
|
171
|
+
with self._lock:
|
|
172
|
+
self._ensure_started()
|
|
173
|
+
|
|
174
|
+
# Create a task lazily if we didn't pre-create it
|
|
175
|
+
if step_id not in self.tasks:
|
|
176
|
+
task_id = self.progress.add_task(
|
|
177
|
+
f"Step {step_id}",
|
|
178
|
+
total=total_items,
|
|
179
|
+
succeeded=items_succeeded,
|
|
180
|
+
errors=items_in_error,
|
|
181
|
+
cache_hits=cache_hits,
|
|
182
|
+
cache_misses=cache_misses,
|
|
183
|
+
)
|
|
184
|
+
self.tasks[step_id] = task_id
|
|
185
|
+
|
|
186
|
+
task_id = self.tasks[step_id]
|
|
187
|
+
color = self.compute_color(items_processed, items_in_error)
|
|
188
|
+
|
|
189
|
+
update_kwargs = {
|
|
190
|
+
"completed": items_processed,
|
|
191
|
+
"succeeded": items_succeeded,
|
|
192
|
+
"errors": items_in_error,
|
|
193
|
+
"description": f"[{color}]Step {step_id}[/{color}]",
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
update_kwargs["cache_hits"] = (
|
|
197
|
+
cache_hits if cache_hits is not None else "-"
|
|
198
|
+
)
|
|
199
|
+
update_kwargs["cache_misses"] = (
|
|
200
|
+
cache_misses if cache_misses is not None else "-"
|
|
201
|
+
)
|
|
202
|
+
if total_items is not None:
|
|
203
|
+
update_kwargs["total"] = total_items
|
|
204
|
+
|
|
205
|
+
self.progress.update(task_id, **update_kwargs)
|
|
206
|
+
|
|
207
|
+
def compute_color(self, items_processed: int, items_in_error: int) -> str:
|
|
208
|
+
# Avoid divide-by-zero
|
|
209
|
+
if items_processed == 0:
|
|
210
|
+
return "green"
|
|
211
|
+
|
|
212
|
+
error_rate = items_in_error / items_processed
|
|
213
|
+
|
|
214
|
+
if error_rate > 0.05:
|
|
215
|
+
return "red"
|
|
216
|
+
elif error_rate > 0.01:
|
|
217
|
+
return "yellow"
|
|
218
|
+
else:
|
|
219
|
+
return "green"
|
|
220
|
+
|
|
221
|
+
def close(self) -> None:
|
|
222
|
+
with self._lock:
|
|
223
|
+
if self._started:
|
|
224
|
+
self.live.stop()
|
|
225
|
+
self._started = False
|
qtype/interpreter/types.py
CHANGED
qtype/semantic/checker.py
CHANGED
|
@@ -10,6 +10,7 @@ from qtype.dsl.model import AWSAuthProvider
|
|
|
10
10
|
from qtype.semantic.model import (
|
|
11
11
|
Agent,
|
|
12
12
|
Application,
|
|
13
|
+
BedrockReranker,
|
|
13
14
|
Decoder,
|
|
14
15
|
DocToTextConverter,
|
|
15
16
|
DocumentEmbedder,
|
|
@@ -20,11 +21,13 @@ from qtype.semantic.model import (
|
|
|
20
21
|
FieldExtractor,
|
|
21
22
|
Flow,
|
|
22
23
|
IndexUpsert,
|
|
24
|
+
ListType,
|
|
23
25
|
LLMInference,
|
|
24
26
|
PromptTemplate,
|
|
25
27
|
SecretReference,
|
|
26
28
|
SQLSource,
|
|
27
29
|
Step,
|
|
30
|
+
VectorIndex,
|
|
28
31
|
VectorSearch,
|
|
29
32
|
)
|
|
30
33
|
|
|
@@ -323,21 +326,29 @@ def _validate_document_embedder(step: DocumentEmbedder) -> None:
|
|
|
323
326
|
|
|
324
327
|
|
|
325
328
|
def _validate_index_upsert(step: IndexUpsert) -> None:
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
(
|
|
332
|
-
|
|
333
|
-
|
|
329
|
+
if isinstance(step.index, VectorIndex):
|
|
330
|
+
# Validate IndexUpsert has exactly one input of type RAGChunk or RAGDocument.
|
|
331
|
+
_validate_exact_input_count(step, 1)
|
|
332
|
+
input_type = step.inputs[0].type
|
|
333
|
+
if input_type not in (RAGChunk, RAGDocument):
|
|
334
|
+
raise QTypeSemanticError(
|
|
335
|
+
(
|
|
336
|
+
f"IndexUpsert step '{step.id}' on Vector Index '{step.index.id}' input must be of type "
|
|
337
|
+
f"'RAGChunk' or 'RAGDocument', found '{input_type}'."
|
|
338
|
+
)
|
|
339
|
+
)
|
|
340
|
+
else:
|
|
341
|
+
# Document index upsert just stores all variables in the message
|
|
342
|
+
if len(step.inputs) < 1:
|
|
343
|
+
raise QTypeSemanticError(
|
|
344
|
+
(
|
|
345
|
+
f"IndexUpsert step '{step.id}' on Document Index '{step.index.id}' must have at least one input."
|
|
346
|
+
)
|
|
334
347
|
)
|
|
335
|
-
)
|
|
336
348
|
|
|
337
349
|
|
|
338
350
|
def _validate_vector_search(step: VectorSearch) -> None:
|
|
339
351
|
"""Validate VectorSearch has exactly one text input and one list[RAGSearchResult] output."""
|
|
340
|
-
from qtype.dsl.model import ListType
|
|
341
352
|
|
|
342
353
|
_validate_exact_input_count(step, 1, PrimitiveTypeEnum.text)
|
|
343
354
|
_validate_exact_output_count(
|
|
@@ -347,7 +358,28 @@ def _validate_vector_search(step: VectorSearch) -> None:
|
|
|
347
358
|
|
|
348
359
|
def _validate_document_search(step: DocumentSearch) -> None:
|
|
349
360
|
"""Validate DocumentSearch has exactly one text input for the query."""
|
|
361
|
+
from qtype.dsl.model import ListType
|
|
362
|
+
|
|
350
363
|
_validate_exact_input_count(step, 1, PrimitiveTypeEnum.text)
|
|
364
|
+
_validate_exact_output_count(
|
|
365
|
+
step, 1, ListType(element_type="SearchResult")
|
|
366
|
+
)
|
|
367
|
+
# TODO: Restore below when ready to decompose into RAG search results for hybrid search
|
|
368
|
+
# actual_type = step.outputs[0].type
|
|
369
|
+
# acceptable_types = set(
|
|
370
|
+
# [
|
|
371
|
+
# ListType(element_type="RAGSearchResult"),
|
|
372
|
+
# ListType(element_type="SearchResult"),
|
|
373
|
+
# ]
|
|
374
|
+
# )
|
|
375
|
+
# if actual_type not in acceptable_types:
|
|
376
|
+
# raise QTypeSemanticError(
|
|
377
|
+
# (
|
|
378
|
+
# f"DocumentSearch step '{step.id}' output must be of type "
|
|
379
|
+
# f"'list[RAGSearchResult]' or 'list[SearchResult]', found "
|
|
380
|
+
# f"'{actual_type}'."
|
|
381
|
+
# )
|
|
382
|
+
# )
|
|
351
383
|
|
|
352
384
|
|
|
353
385
|
def _validate_flow(flow: Flow) -> None:
|
|
@@ -523,25 +555,53 @@ def _validate_application(application: Application) -> None:
|
|
|
523
555
|
)
|
|
524
556
|
|
|
525
557
|
|
|
558
|
+
def _validate_bedrock_reranker(reranker: BedrockReranker) -> None:
|
|
559
|
+
"""Validate BedrockReranker configuration."""
|
|
560
|
+
_validate_exact_output_count(
|
|
561
|
+
reranker, 1, ListType(element_type="SearchResult")
|
|
562
|
+
)
|
|
563
|
+
_validate_exact_input_count(reranker, 2)
|
|
564
|
+
# Confirm at least one input is text (the query)
|
|
565
|
+
input_types = [inp.type for inp in reranker.inputs] # type: ignore
|
|
566
|
+
if PrimitiveTypeEnum.text not in input_types:
|
|
567
|
+
raise QTypeSemanticError(
|
|
568
|
+
(
|
|
569
|
+
f"BedrockReranker step '{reranker.id}' must have at least one "
|
|
570
|
+
f"input of type 'text' for the query, found input types: "
|
|
571
|
+
f"{input_types}."
|
|
572
|
+
)
|
|
573
|
+
)
|
|
574
|
+
# Confirm at least one input is list[SearchResult] (the results to rerank)
|
|
575
|
+
if ListType(element_type="SearchResult") not in input_types:
|
|
576
|
+
raise QTypeSemanticError(
|
|
577
|
+
(
|
|
578
|
+
f"BedrockReranker step '{reranker.id}' must have at least one "
|
|
579
|
+
f"input of type 'list[SearchResult]' for the results to rerank, "
|
|
580
|
+
f"found input types: {input_types}."
|
|
581
|
+
)
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
|
|
526
585
|
# Mapping of types to their validation functions
|
|
527
586
|
_VALIDATORS = {
|
|
528
587
|
Agent: _validate_agent,
|
|
529
588
|
Application: _validate_application,
|
|
530
|
-
PromptTemplate: _validate_prompt_template,
|
|
531
589
|
AWSAuthProvider: _validate_aws_auth,
|
|
532
|
-
|
|
590
|
+
BedrockReranker: _validate_bedrock_reranker,
|
|
533
591
|
Decoder: _validate_decoder,
|
|
534
|
-
Echo: _validate_echo,
|
|
535
|
-
FieldExtractor: _validate_field_extractor,
|
|
536
|
-
SQLSource: _validate_sql_source,
|
|
537
|
-
DocumentSource: _validate_document_source,
|
|
538
592
|
DocToTextConverter: _validate_doc_to_text_converter,
|
|
539
|
-
DocumentSplitter: _validate_document_splitter,
|
|
540
593
|
DocumentEmbedder: _validate_document_embedder,
|
|
541
|
-
IndexUpsert: _validate_index_upsert,
|
|
542
|
-
VectorSearch: _validate_vector_search,
|
|
543
594
|
DocumentSearch: _validate_document_search,
|
|
595
|
+
DocumentSource: _validate_document_source,
|
|
596
|
+
DocumentSplitter: _validate_document_splitter,
|
|
597
|
+
Echo: _validate_echo,
|
|
598
|
+
FieldExtractor: _validate_field_extractor,
|
|
544
599
|
Flow: _validate_flow,
|
|
600
|
+
IndexUpsert: _validate_index_upsert,
|
|
601
|
+
LLMInference: _validate_llm_inference,
|
|
602
|
+
PromptTemplate: _validate_prompt_template,
|
|
603
|
+
SQLSource: _validate_sql_source,
|
|
604
|
+
VectorSearch: _validate_vector_search,
|
|
545
605
|
}
|
|
546
606
|
|
|
547
607
|
|
qtype/semantic/model.py
CHANGED
|
@@ -558,6 +558,10 @@ class FieldExtractor(Step):
|
|
|
558
558
|
...,
|
|
559
559
|
description="JSONPath expression to extract data from the input. Uses jsonpath-ng syntax.",
|
|
560
560
|
)
|
|
561
|
+
fail_on_missing: bool = Field(
|
|
562
|
+
True,
|
|
563
|
+
description="Whether to raise an error if the JSONPath matches no data. If False, returns None.",
|
|
564
|
+
)
|
|
561
565
|
|
|
562
566
|
|
|
563
567
|
class InvokeEmbedding(Step, ConcurrentStepMixin):
|
|
@@ -627,6 +631,12 @@ class PromptTemplate(Step):
|
|
|
627
631
|
)
|
|
628
632
|
|
|
629
633
|
|
|
634
|
+
class Reranker(Step):
|
|
635
|
+
"""Reranks a list of documents based on relevance to a query using an LLM."""
|
|
636
|
+
|
|
637
|
+
type: Literal["Reranker"] = Field("Reranker")
|
|
638
|
+
|
|
639
|
+
|
|
630
640
|
class Search(Step):
|
|
631
641
|
"""Base class for search operations against indexes."""
|
|
632
642
|
|
|
@@ -637,6 +647,10 @@ class Search(Step):
|
|
|
637
647
|
index: Index = Field(
|
|
638
648
|
..., description="Index to search against (object or ID reference)."
|
|
639
649
|
)
|
|
650
|
+
default_top_k: int | None = Field(
|
|
651
|
+
10,
|
|
652
|
+
description="Number of top results to retrieve if not provided in the inputs.",
|
|
653
|
+
)
|
|
640
654
|
|
|
641
655
|
|
|
642
656
|
class Source(Step):
|
|
@@ -663,6 +677,10 @@ class DocumentIndex(Index):
|
|
|
663
677
|
...,
|
|
664
678
|
description="URL endpoint for the search cluster (e.g., https://my-cluster.es.amazonaws.com).",
|
|
665
679
|
)
|
|
680
|
+
id_field: str | None = Field(
|
|
681
|
+
None,
|
|
682
|
+
description="Field name to use as document ID. If not specified, auto-detects from: _id, id, doc_id, document_id, or uuid. If all are missing, a UUID is generated.",
|
|
683
|
+
)
|
|
666
684
|
|
|
667
685
|
|
|
668
686
|
class VectorIndex(Index):
|
|
@@ -699,19 +717,41 @@ class Agent(LLMInference):
|
|
|
699
717
|
)
|
|
700
718
|
|
|
701
719
|
|
|
720
|
+
class BedrockReranker(Reranker, ConcurrentStepMixin):
|
|
721
|
+
"""Reranks documents using an AWS Bedrock model."""
|
|
722
|
+
|
|
723
|
+
type: Literal["BedrockReranker"] = Field("BedrockReranker")
|
|
724
|
+
auth: AWSAuthProvider | None = Field(
|
|
725
|
+
None, description="AWS authorization provider for Bedrock access."
|
|
726
|
+
)
|
|
727
|
+
model_id: str = Field(
|
|
728
|
+
...,
|
|
729
|
+
description="Bedrock model ID to use for reranking. See https://docs.aws.amazon.com/bedrock/latest/userguide/rerank-supported.html",
|
|
730
|
+
)
|
|
731
|
+
num_results: int | None = Field(
|
|
732
|
+
None, description="Return this many results."
|
|
733
|
+
)
|
|
734
|
+
|
|
735
|
+
|
|
702
736
|
class DocumentSearch(Search, ConcurrentStepMixin):
|
|
703
737
|
"""Performs document search against a document index."""
|
|
704
738
|
|
|
705
739
|
type: Literal["DocumentSearch"] = Field("DocumentSearch")
|
|
740
|
+
index: DocumentIndex = Field(
|
|
741
|
+
..., description="Index to search against (object or ID reference)."
|
|
742
|
+
)
|
|
743
|
+
query_args: dict[str, Any] = Field(
|
|
744
|
+
{"type": "best_fields", "fields": ["*"]},
|
|
745
|
+
description="The arguments (other than 'query') to specify to the query shape (see https://docs.opensearch.org/latest/query-dsl/full-text/multi-match/).",
|
|
746
|
+
)
|
|
706
747
|
|
|
707
748
|
|
|
708
749
|
class VectorSearch(Search, BatchableStepMixin):
|
|
709
750
|
"""Performs vector similarity search against a vector index."""
|
|
710
751
|
|
|
711
752
|
type: Literal["VectorSearch"] = Field("VectorSearch")
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
description="Number of top results to retrieve if not provided in the inputs.",
|
|
753
|
+
index: VectorIndex = Field(
|
|
754
|
+
..., description="Index to search against (object or ID reference)."
|
|
715
755
|
)
|
|
716
756
|
|
|
717
757
|
|
qtype/semantic/resolver.py
CHANGED
|
@@ -75,8 +75,10 @@ def to_semantic_ir(
|
|
|
75
75
|
# If the object is a list, we will resolve each item in the list.
|
|
76
76
|
return [to_semantic_ir(item, symbol_table) for item in dslobj] # type: ignore
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
# Return these types as-is as they are not changed
|
|
79
|
+
if isinstance(dslobj, dsl.Enum) or isinstance(
|
|
80
|
+
dslobj, base_types.CacheConfig
|
|
81
|
+
):
|
|
80
82
|
return dslobj
|
|
81
83
|
|
|
82
84
|
if _is_dsl_type(_resolve_forward_ref(type(dslobj))):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qtype
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
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
|
|
@@ -23,16 +23,26 @@ Provides-Extra: interpreter
|
|
|
23
23
|
Requires-Dist: aiostream>=0.7.1; extra == "interpreter"
|
|
24
24
|
Requires-Dist: arize-phoenix-otel>=0.12.1; extra == "interpreter"
|
|
25
25
|
Requires-Dist: boto3>=1.34.0; extra == "interpreter"
|
|
26
|
+
Requires-Dist: datasets>=4.4.1; extra == "interpreter"
|
|
27
|
+
Requires-Dist: diskcache>=5.6.3; extra == "interpreter"
|
|
26
28
|
Requires-Dist: docling>=2.55.1; extra == "interpreter"
|
|
27
|
-
Requires-Dist:
|
|
29
|
+
Requires-Dist: docx2txt>=0.9; extra == "interpreter"
|
|
28
30
|
Requires-Dist: fastapi>=0.116.1; extra == "interpreter"
|
|
31
|
+
Requires-Dist: jsonpath-ng>=1.7.0; extra == "interpreter"
|
|
32
|
+
Requires-Dist: langfuse>=3.9.0; extra == "interpreter"
|
|
29
33
|
Requires-Dist: llama-index-embeddings-bedrock>=0.5.2; extra == "interpreter"
|
|
30
34
|
Requires-Dist: llama-index-embeddings-openai>=0.3.1; extra == "interpreter"
|
|
31
35
|
Requires-Dist: llama-index-llms-bedrock-converse>=0.10.5; extra == "interpreter"
|
|
32
36
|
Requires-Dist: llama-index-llms-bedrock>=0.3.8; extra == "interpreter"
|
|
37
|
+
Requires-Dist: llama-index-llms-vertex>=0.6.1; extra == "interpreter"
|
|
38
|
+
Requires-Dist: llama-index-postprocessor-bedrock-rerank>=0.5.1; extra == "interpreter"
|
|
39
|
+
Requires-Dist: llama-index-readers-huggingface-fs>=0.4.1; extra == "interpreter"
|
|
40
|
+
Requires-Dist: llama-index-vector-stores-qdrant>=0.8.6; extra == "interpreter"
|
|
33
41
|
Requires-Dist: llama-index>=0.12.45; extra == "interpreter"
|
|
34
42
|
Requires-Dist: openinference-instrumentation-llama-index>=4.3.4; extra == "interpreter"
|
|
35
43
|
Requires-Dist: opensearch-py>=2.7.0; extra == "interpreter"
|
|
44
|
+
Requires-Dist: opentelemetry-exporter-otlp>=1.35.0; extra == "interpreter"
|
|
45
|
+
Requires-Dist: opentelemetry-sdk>=1.35.0; extra == "interpreter"
|
|
36
46
|
Requires-Dist: pandas>=2.2.3; extra == "interpreter"
|
|
37
47
|
Requires-Dist: psycopg2-binary>=2.9.10; extra == "interpreter"
|
|
38
48
|
Requires-Dist: pyarrow>=21.0.0; extra == "interpreter"
|
|
@@ -41,15 +51,6 @@ Requires-Dist: python-magic>=0.4.27; extra == "interpreter"
|
|
|
41
51
|
Requires-Dist: s3fs>=2025.7.0; extra == "interpreter"
|
|
42
52
|
Requires-Dist: sqlalchemy>=2.0.42; extra == "interpreter"
|
|
43
53
|
Requires-Dist: uvicorn[standard]>=0.35.0; extra == "interpreter"
|
|
44
|
-
Requires-Dist: llama-index-llms-vertex>=0.6.1; extra == "interpreter"
|
|
45
|
-
Requires-Dist: langfuse>=3.9.0; extra == "interpreter"
|
|
46
|
-
Requires-Dist: opentelemetry-exporter-otlp>=1.35.0; extra == "interpreter"
|
|
47
|
-
Requires-Dist: opentelemetry-sdk>=1.35.0; extra == "interpreter"
|
|
48
|
-
Requires-Dist: docx2txt>=0.9; extra == "interpreter"
|
|
49
|
-
Requires-Dist: llama-index-vector-stores-qdrant>=0.8.6; extra == "interpreter"
|
|
50
|
-
Requires-Dist: jsonpath-ng>=1.7.0; extra == "interpreter"
|
|
51
|
-
Requires-Dist: llama-index-readers-huggingface-fs>=0.4.1; extra == "interpreter"
|
|
52
|
-
Requires-Dist: datasets>=4.4.1; extra == "interpreter"
|
|
53
54
|
Dynamic: license-file
|
|
54
55
|
|
|
55
56
|
# QType
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
qtype/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
qtype/cli.py,sha256=
|
|
2
|
+
qtype/cli.py,sha256=AC2i9dROss5JsEhbaRpIz4kHVvm0Tq-ope3ENL8Qw5w,4797
|
|
3
3
|
qtype/application/__init__.py,sha256=WS3x0b0NRt-nRmj1trsytlvMpQS5KN7Hi6THGfY8bKE,230
|
|
4
4
|
qtype/application/documentation.py,sha256=ifmdt0jBW410baQuCUxovYDQQj-kxPZ4fmf6rWps9JY,4988
|
|
5
|
-
qtype/application/facade.py,sha256=
|
|
5
|
+
qtype/application/facade.py,sha256=JjexkpTzP-aAJHs4AaxJbB4CU10jn3zcPFpQ6FYWJFg,5803
|
|
6
6
|
qtype/application/commons/__init__.py,sha256=QyWAB2cvimM4DxNo2oBFCGkfBikH-ZeMBMGWmJcq4Uc,135
|
|
7
7
|
qtype/application/commons/tools.py,sha256=U_jJdVN2NO5v9b3qb6dPIiVykfal6tp6NvcLGWR6HC8,5035
|
|
8
8
|
qtype/application/converters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -15,59 +15,61 @@ qtype/base/logging.py,sha256=eqStjILlmhNryYRqUiyTdDHoUoiLKSY8J0GevvzvTKQ,1075
|
|
|
15
15
|
qtype/base/types.py,sha256=zkweSHfpP6MrDEHzEpEWTZ-xVxQLZJj1QhKv-Mj4s0A,6834
|
|
16
16
|
qtype/commands/__init__.py,sha256=Qo4M07zm5I63r8STxDjvt5fhP1jygdXTsExNGELkefc,257
|
|
17
17
|
qtype/commands/convert.py,sha256=wh2-MSBlnMU5peAzVeQcGqqFzQbeCuL5WC5-EDZ-TFM,4636
|
|
18
|
-
qtype/commands/generate.py,sha256=
|
|
19
|
-
qtype/commands/run.py,sha256=
|
|
18
|
+
qtype/commands/generate.py,sha256=OQEkuh3dTVu6ZUNAuH_HkU-9YktYySL0qjTdrz28FY8,7285
|
|
19
|
+
qtype/commands/run.py,sha256=rDIiDioWU-dNuw39F12Bb6buknsNGzzVhd41i9Yms8Y,6633
|
|
20
20
|
qtype/commands/serve.py,sha256=lb5akSZ8fYLlCl8u8HDFFk6kyCHHwSRnP5wNzZry8sg,3216
|
|
21
21
|
qtype/commands/validate.py,sha256=f0aOk6A08910bFfamfg8xafByADMx4EktXAGMrEeUXU,3067
|
|
22
22
|
qtype/commands/visualize.py,sha256=J1eqwaVWTteGzib84g7Qtp0JlX9wIMmRQWSv1RhAns8,3763
|
|
23
23
|
qtype/dsl/__init__.py,sha256=clrmM1ZlK6c0Le_183eo5bc9dDK53Ebp-vH5ZVfwhfw,397
|
|
24
24
|
qtype/dsl/custom_types.py,sha256=N3qswimv0foH40YDubHaTZ3HYF9RUbZ2x5eQ4i798Ko,2901
|
|
25
|
-
qtype/dsl/domain_types.py,sha256
|
|
25
|
+
qtype/dsl/domain_types.py,sha256=-pX74DKwrRanoXBxYqAdN_f44ike6ssRV3tZ20R2PhQ,4319
|
|
26
26
|
qtype/dsl/linker.py,sha256=c7PPTULy7_z_9u_qeseIaomR_B8kBa9YzOhQpjeGaSM,12975
|
|
27
27
|
qtype/dsl/loader.py,sha256=mht0BqfmyTNHIEDaF3iTEmYQLJBP5GIZULwexxw9Dpg,9771
|
|
28
|
-
qtype/dsl/model.py,sha256
|
|
28
|
+
qtype/dsl/model.py,sha256=0yKl3fKAWQ_BDH-z62oI47IiJQhaH6HFzYRD1tUZhME,40860
|
|
29
29
|
qtype/dsl/parser.py,sha256=jpz32zyvOIo-R6Xr1lshzQiGfeo-2-fZczkdfURBufo,5487
|
|
30
30
|
qtype/dsl/types.py,sha256=k6cgThA287bZ_pvTKQvxWhatcYCPNne8zpqOYOvLvOg,1687
|
|
31
31
|
qtype/interpreter/__init__.py,sha256=IaRF90JLFbsTLKz9LTOMI_Pz4xwVaEyXPNaXV7sLou8,43
|
|
32
32
|
qtype/interpreter/api.py,sha256=V7hjsmDhe1IwbcwdM5bnPGBiwH3TtlMLjUJdGJumCdA,4193
|
|
33
|
-
qtype/interpreter/conversions.py,sha256=
|
|
34
|
-
qtype/interpreter/converters.py,sha256=
|
|
33
|
+
qtype/interpreter/conversions.py,sha256=SHtVVN8k36_iODKvHt1MV6V08GRaEBwE4yCN6VQvlHA,20986
|
|
34
|
+
qtype/interpreter/converters.py,sha256=gWyfizl7d-DT6jJ2aOrneUcZcwB-LdMDEvl-VT0-mLQ,2348
|
|
35
35
|
qtype/interpreter/endpoints.py,sha256=un4iCYCk86lYKpTDFdzlByvebdctNwRF3n4oD4ZwpTw,11946
|
|
36
|
-
qtype/interpreter/flow.py,sha256=
|
|
36
|
+
qtype/interpreter/flow.py,sha256=eitRE1Hh6avmMzjLKKcrWztviSzJHFu4yZSbtIeMLQ0,6188
|
|
37
37
|
qtype/interpreter/metadata_api.py,sha256=LfJjt9atsgiAra6aVBXLoJrPa06_CBUagYysT556nt8,3267
|
|
38
38
|
qtype/interpreter/resource_cache.py,sha256=K0kzpm223COWk7FN9qyOvNOEoOcABR4yLeADL9ekE_o,1188
|
|
39
|
+
qtype/interpreter/rich_progress.py,sha256=J7TokOIqIUVWJZCfGEexQCwvvj6b1SjRtKThk2DU0CA,6761
|
|
39
40
|
qtype/interpreter/telemetry.py,sha256=Hcwd9sMW55LejgOIpPwjkWsmTvB2vnpSr4TshTAKljk,4901
|
|
40
|
-
qtype/interpreter/types.py,sha256=
|
|
41
|
+
qtype/interpreter/types.py,sha256=YBwav_frbFptGrIw60ebI-jfAu28GQUZEQ9mwfCjLFc,10045
|
|
41
42
|
qtype/interpreter/typing.py,sha256=Ka5wkkpQFZQKgKMCR3p7bD7W4uHpOryevEi-isc2RCw,3888
|
|
42
43
|
qtype/interpreter/auth/__init__.py,sha256=L98AxaSizb6LMdXEr8FGe9MBtPBnfCeWxjI0oi7sg_o,62
|
|
43
44
|
qtype/interpreter/auth/aws.py,sha256=eMXyEBqzv7I243fS-A1zHPQkN--yPFEh1Hxp4rxmyEs,8154
|
|
44
45
|
qtype/interpreter/auth/cache.py,sha256=uVyJ_jkbprRdlvbnm1DVIaYyTDLEsPXvi3xjuRneH2k,1825
|
|
45
46
|
qtype/interpreter/auth/generic.py,sha256=WHXu3SxWzxJn_bv6R20Aod84Vwe73xTYHx754dY1MSg,6178
|
|
46
|
-
qtype/interpreter/base/base_step_executor.py,sha256=
|
|
47
|
+
qtype/interpreter/base/base_step_executor.py,sha256=DFQOwRVXStxPLov-unG4IXq-iBQ66JVPeetNnUcdlZ8,16497
|
|
47
48
|
qtype/interpreter/base/batch_step_executor.py,sha256=g5_yPd5VTy_slW5ZXyamgFyTRd0CoaeVfDHj8x4PvUk,5906
|
|
48
49
|
qtype/interpreter/base/exceptions.py,sha256=7CIexzDfIjvAA0c6qwg4jsDcTQM1pKQLj6szxcqil_c,1586
|
|
49
|
-
qtype/interpreter/base/executor_context.py,sha256=
|
|
50
|
-
qtype/interpreter/base/factory.py,sha256=
|
|
51
|
-
qtype/interpreter/base/progress_tracker.py,sha256=
|
|
50
|
+
qtype/interpreter/base/executor_context.py,sha256=qDMb7GJebCw3E6oMiCSpu0-aRq-l6MPx6yPLwM2quOs,3561
|
|
51
|
+
qtype/interpreter/base/factory.py,sha256=9etq_vvds-C9QrwVutkPZmGwrMJ_WZwrkeXOzjOUEpk,3534
|
|
52
|
+
qtype/interpreter/base/progress_tracker.py,sha256=zHtTp0JGrn1M3wNEEVfkwQmuHD-WKXV7tv4fDdHv1xs,3488
|
|
52
53
|
qtype/interpreter/base/secrets.py,sha256=74NoU0Fx96vva6LGWXk7EkvFWD4uZEk12NjWrGHWZTc,11241
|
|
53
|
-
qtype/interpreter/base/step_cache.py,sha256
|
|
54
|
+
qtype/interpreter/base/step_cache.py,sha256=iNtEFN-bvfG5S5iPhXR_U7iVtK-RWh9_nhCRetckukU,2432
|
|
54
55
|
qtype/interpreter/base/stream_emitter.py,sha256=8l5bCFTjMA3Takjh51QdWw8ERb7_GamHVoU-x6xkG5I,13828
|
|
55
56
|
qtype/interpreter/executors/agent_executor.py,sha256=pll5tdUD977fmMMfoXVhY-dLQttv-aqT04gyjrF6seo,8378
|
|
56
57
|
qtype/interpreter/executors/aggregate_executor.py,sha256=Z3NJekpeo7aqqvOcXQqb6d6t9g4UB1r3N1lSV9EwZq4,3495
|
|
58
|
+
qtype/interpreter/executors/bedrock_reranker_executor.py,sha256=p25BMmM1paAlK2vfpwJ9T5st_2B-bmZoDnVFp9ynZIY,7154
|
|
57
59
|
qtype/interpreter/executors/decoder_executor.py,sha256=KqLhnhiclMIcUNf3bu7H4vDAOXCQeVO0rc2hIXm1qZ4,5610
|
|
58
60
|
qtype/interpreter/executors/doc_to_text_executor.py,sha256=ZkTtKUL0BfNIiuj-OcYybn1f0By6ujRmd1U4VEAtJt4,3804
|
|
59
|
-
qtype/interpreter/executors/document_embedder_executor.py,sha256=
|
|
60
|
-
qtype/interpreter/executors/document_search_executor.py,sha256=
|
|
61
|
+
qtype/interpreter/executors/document_embedder_executor.py,sha256=wvARlFPb2dmMdxjW8L1422a-XmcUVxEJXWf24bDR9BE,3529
|
|
62
|
+
qtype/interpreter/executors/document_search_executor.py,sha256=ZmKAt__jC5cxZY0gSm9AgpC6n7MFavTHE01tQED3zFk,4051
|
|
61
63
|
qtype/interpreter/executors/document_source_executor.py,sha256=ZpBrBaE16YeRk750TxvE08NnCIUzArjESZImESomaIo,4247
|
|
62
|
-
qtype/interpreter/executors/document_splitter_executor.py,sha256=
|
|
64
|
+
qtype/interpreter/executors/document_splitter_executor.py,sha256=2mzrkkNqsPb5erDUd_VapnrykgywMXGXZnkWT1YJe_w,3815
|
|
63
65
|
qtype/interpreter/executors/echo_executor.py,sha256=oQUgzQTHruT4on7wgEBOcikwOy6KP82d5zrul5QLoRU,2194
|
|
64
|
-
qtype/interpreter/executors/field_extractor_executor.py,sha256=
|
|
66
|
+
qtype/interpreter/executors/field_extractor_executor.py,sha256=geDmT6GyvbDDJvPX1hPChAydDZ_LSHlOdskK-6ZGvbI,5796
|
|
65
67
|
qtype/interpreter/executors/file_source_executor.py,sha256=OUT_zJrYN3iFMUgLECde93C4rv8PthcQsuJ--CJvEsI,3605
|
|
66
68
|
qtype/interpreter/executors/file_writer_executor.py,sha256=x4BpgdXM7Xhz1tJJ5MmBIjFO4y80VC1V1ow3tox_Xrw,4099
|
|
67
|
-
qtype/interpreter/executors/index_upsert_executor.py,sha256=
|
|
68
|
-
qtype/interpreter/executors/invoke_embedding_executor.py,sha256=
|
|
69
|
+
qtype/interpreter/executors/index_upsert_executor.py,sha256=5MxG3GX2bbjX6jhCpCdEZ0YFJOshn649cfaOT50PLCA,8518
|
|
70
|
+
qtype/interpreter/executors/invoke_embedding_executor.py,sha256=OPvd--x8iimjODLJkRpRfQDahL8LnYaPy3A8WVB5h00,3311
|
|
69
71
|
qtype/interpreter/executors/invoke_flow_executor.py,sha256=U30cYM3F_zy1_2CD1Dde59xyZD0rDa5W46lST1hxF6s,1682
|
|
70
|
-
qtype/interpreter/executors/invoke_tool_executor.py,sha256=
|
|
72
|
+
qtype/interpreter/executors/invoke_tool_executor.py,sha256=hhbE8YTr0x5-kz_xsvdWGGzkLkVdvDoAVAF-3ZUK5as,12786
|
|
71
73
|
qtype/interpreter/executors/llm_inference_executor.py,sha256=A6b_Ns_734TCn_DMhdNSqWc5qX970FryhpsX_jtEu_4,9593
|
|
72
74
|
qtype/interpreter/executors/prompt_template_executor.py,sha256=AKZWQvsoY2fQoSg5N8_R7LIlC8AKTwjNKOz_MuvASc0,2700
|
|
73
75
|
qtype/interpreter/executors/sql_source_executor.py,sha256=-fUWQK2S7NBe3oJG1lmkNRujASHFyXu3H8h-WrobbQw,3932
|
|
@@ -120,15 +122,15 @@ qtype/interpreter/ui/_next/static/media/9610d9e46709d722-s.woff2,sha256=N08hXnJf
|
|
|
120
122
|
qtype/interpreter/ui/_next/static/media/ba015fad6dcf6784-s.woff2,sha256=92BKU6ACUPZttLR91EMnzipD9u3shQ1SF7uAI4gZ790,15292
|
|
121
123
|
qtype/semantic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
122
124
|
qtype/semantic/base_types.py,sha256=wfUlT0gV3_Mk1xLLI64SSXCB9GFmn29yz5adTaHrsOI,1540
|
|
123
|
-
qtype/semantic/checker.py,sha256=
|
|
125
|
+
qtype/semantic/checker.py,sha256=TJTxSIMXNERpry98jqFNd8Ga5ljTvHOVosYb0AYbpbc,22291
|
|
124
126
|
qtype/semantic/generate.py,sha256=s56N0ollRJVVxy6RUKZWFFReKYcSSVw33ixvT2MQRuA,21116
|
|
125
127
|
qtype/semantic/loader.py,sha256=QRhTc_AJfsWSMn8ThaW60GmIGjFMN-3bBUy4pktFjz4,3041
|
|
126
|
-
qtype/semantic/model.py,sha256=
|
|
127
|
-
qtype/semantic/resolver.py,sha256=
|
|
128
|
+
qtype/semantic/model.py,sha256=7yZ-Ufuo-gNJbhFXALuKZxILdhNB5zbL3a3oQQARI8g,28602
|
|
129
|
+
qtype/semantic/resolver.py,sha256=bWPCSB8KJpVqN_n41U_r-qzUiT8vAMBOD3pOGmxL6TY,4618
|
|
128
130
|
qtype/semantic/visualize.py,sha256=thjrZcfQuZJWrZ9EMAPhAa2kNikR5rLIJrfcD3hJ8XY,17426
|
|
129
|
-
qtype-0.1.
|
|
130
|
-
qtype-0.1.
|
|
131
|
-
qtype-0.1.
|
|
132
|
-
qtype-0.1.
|
|
133
|
-
qtype-0.1.
|
|
134
|
-
qtype-0.1.
|
|
131
|
+
qtype-0.1.2.dist-info/licenses/LICENSE,sha256=1KA5EgYBSR0O6nCH2HEvk6Di53YKJ9r_VCR7G8G8qAY,11341
|
|
132
|
+
qtype-0.1.2.dist-info/METADATA,sha256=lxoxEpkpLqsOuf7OIqjBliN6tq0YlUUXwfvty3CxGdk,5657
|
|
133
|
+
qtype-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
134
|
+
qtype-0.1.2.dist-info/entry_points.txt,sha256=5y4vj8RLvgl2tXSj-Hm7v5-Tn3kP4-UonjNoN-mfaQE,41
|
|
135
|
+
qtype-0.1.2.dist-info/top_level.txt,sha256=ONroH5B0mZ51jr7NSWCK0weFwwCO7wBLmyVS1YqNU14,6
|
|
136
|
+
qtype-0.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|