qtype 0.1.11__py3-none-any.whl → 0.1.12__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.
- docs/Concepts/mental-model-and-philosophy.md +363 -0
- docs/Contributing/index.md +276 -0
- docs/Contributing/roadmap.md +81 -0
- docs/Decisions/ADR-001-Chat-vs-Completion-Endpoint-Features.md +56 -0
- docs/Gallery/dataflow_pipelines.md +80 -0
- docs/Gallery/dataflow_pipelines.mermaid +45 -0
- docs/Gallery/research_assistant.md +98 -0
- docs/Gallery/research_assistant.mermaid +42 -0
- docs/Gallery/simple_chatbot.md +36 -0
- docs/Gallery/simple_chatbot.mermaid +35 -0
- docs/How To/Authentication/configure_aws_authentication.md +60 -0
- docs/How To/Authentication/use_api_key_authentication.md +40 -0
- docs/How To/Command Line Usage/load_multiple_inputs_from_files.md +62 -0
- docs/How To/Command Line Usage/pass_inputs_on_the_cli.md +52 -0
- docs/How To/Command Line Usage/serve_with_auto_reload.md +26 -0
- docs/How To/Data Processing/adjust_concurrency.md +41 -0
- docs/How To/Data Processing/cache_step_results.md +71 -0
- docs/How To/Data Processing/decode_json_xml.md +24 -0
- docs/How To/Data Processing/explode_collections.md +40 -0
- docs/How To/Data Processing/gather_results.md +68 -0
- docs/How To/Data Processing/read_data_from_files.md +35 -0
- docs/How To/Data Processing/read_sql_databases.md +47 -0
- docs/How To/Data Processing/write_data_to_file.md +40 -0
- docs/How To/Invoke Models/call_large_language_models.md +51 -0
- docs/How To/Invoke Models/create_embeddings.md +49 -0
- docs/How To/Invoke Models/reuse_prompts_with_templates.md +39 -0
- docs/How To/Language Features/include_qtype_yaml.md +45 -0
- docs/How To/Language Features/include_raw_text_from_other_files.md +47 -0
- docs/How To/Language Features/reference_entities_by_id.md +51 -0
- docs/How To/Language Features/use_environment_variables.md +47 -0
- docs/How To/Language Features/use_qtype_mcp.md +59 -0
- docs/How To/Observability & Debugging/trace_calls_with_open_telemetry.md +49 -0
- docs/How To/Observability & Debugging/validate_qtype_yaml.md +35 -0
- docs/How To/Observability & Debugging/visualize_application_architecture.md +61 -0
- docs/How To/Observability & Debugging/visualize_example.mermaid +35 -0
- docs/How To/Qtype Server/flow_as_ui.png +0 -0
- docs/How To/Qtype Server/serve_flows_as_apis.md +40 -0
- docs/How To/Qtype Server/serve_flows_as_ui.md +42 -0
- docs/How To/Qtype Server/use_conversational_interfaces.md +59 -0
- docs/How To/Qtype Server/use_variables_with_ui_hints.md +47 -0
- docs/How To/Tools & Integration/bind_tool_inputs_and_outputs.md +48 -0
- docs/How To/Tools & Integration/create_tools_from_openapi_specifications.md +89 -0
- docs/How To/Tools & Integration/create_tools_from_python_modules.md +90 -0
- docs/Reference/cli.md +338 -0
- docs/Reference/plugins.md +95 -0
- docs/Reference/semantic-validation-rules.md +179 -0
- docs/Tutorials/01-first-qtype-application.md +248 -0
- docs/Tutorials/02-conversational-chatbot.md +327 -0
- docs/Tutorials/03-structured-data.md +481 -0
- docs/Tutorials/04-tools-and-function-calling.md +483 -0
- docs/Tutorials/example_chat.png +0 -0
- docs/Tutorials/index.md +92 -0
- docs/components/APIKeyAuthProvider.md +7 -0
- docs/components/APITool.md +10 -0
- docs/components/AWSAuthProvider.md +13 -0
- docs/components/AWSSecretManager.md +5 -0
- docs/components/Agent.md +6 -0
- docs/components/Aggregate.md +8 -0
- docs/components/AggregateStats.md +7 -0
- docs/components/Application.md +22 -0
- docs/components/AuthorizationProvider.md +6 -0
- docs/components/AuthorizationProviderList.md +5 -0
- docs/components/BearerTokenAuthProvider.md +6 -0
- docs/components/BedrockReranker.md +8 -0
- docs/components/ChatContent.md +7 -0
- docs/components/ChatMessage.md +6 -0
- docs/components/ConstantPath.md +5 -0
- docs/components/CustomType.md +7 -0
- docs/components/Decoder.md +8 -0
- docs/components/DecoderFormat.md +8 -0
- docs/components/DocToTextConverter.md +7 -0
- docs/components/Document.md +7 -0
- docs/components/DocumentEmbedder.md +7 -0
- docs/components/DocumentIndex.md +7 -0
- docs/components/DocumentSearch.md +7 -0
- docs/components/DocumentSource.md +12 -0
- docs/components/DocumentSplitter.md +10 -0
- docs/components/Echo.md +8 -0
- docs/components/Embedding.md +7 -0
- docs/components/EmbeddingModel.md +6 -0
- docs/components/FieldExtractor.md +20 -0
- docs/components/FileSource.md +6 -0
- docs/components/FileWriter.md +7 -0
- docs/components/Flow.md +14 -0
- docs/components/FlowInterface.md +7 -0
- docs/components/Index.md +8 -0
- docs/components/IndexUpsert.md +6 -0
- docs/components/InvokeEmbedding.md +7 -0
- docs/components/InvokeFlow.md +8 -0
- docs/components/InvokeTool.md +8 -0
- docs/components/LLMInference.md +9 -0
- docs/components/ListType.md +5 -0
- docs/components/Memory.md +8 -0
- docs/components/MessageRole.md +14 -0
- docs/components/Model.md +10 -0
- docs/components/ModelList.md +5 -0
- docs/components/OAuth2AuthProvider.md +9 -0
- docs/components/PrimitiveTypeEnum.md +21 -0
- docs/components/PromptTemplate.md +7 -0
- docs/components/PythonFunctionTool.md +7 -0
- docs/components/RAGChunk.md +7 -0
- docs/components/RAGDocument.md +10 -0
- docs/components/RAGSearchResult.md +8 -0
- docs/components/Reranker.md +5 -0
- docs/components/SQLSource.md +8 -0
- docs/components/Search.md +7 -0
- docs/components/SearchResult.md +7 -0
- docs/components/SecretManager.md +7 -0
- docs/components/SecretReference.md +7 -0
- docs/components/Source.md +6 -0
- docs/components/Step.md +9 -0
- docs/components/TelemetrySink.md +9 -0
- docs/components/Tool.md +9 -0
- docs/components/ToolList.md +5 -0
- docs/components/ToolParameter.md +6 -0
- docs/components/TypeList.md +5 -0
- docs/components/Variable.md +6 -0
- docs/components/VariableList.md +5 -0
- docs/components/VectorIndex.md +7 -0
- docs/components/VectorSearch.md +6 -0
- docs/components/VertexAuthProvider.md +9 -0
- docs/components/Writer.md +5 -0
- docs/example_ui.png +0 -0
- docs/index.md +81 -0
- docs/legacy_how_tos/Configuration/modular-yaml.md +366 -0
- docs/legacy_how_tos/Configuration/phoenix_projects.png +0 -0
- docs/legacy_how_tos/Configuration/phoenix_traces.png +0 -0
- docs/legacy_how_tos/Configuration/reference-by-id.md +251 -0
- docs/legacy_how_tos/Configuration/telemetry-setup.md +259 -0
- docs/legacy_how_tos/Data Types/custom-types.md +52 -0
- docs/legacy_how_tos/Data Types/domain-types.md +113 -0
- docs/legacy_how_tos/Debugging/visualize-apps.md +147 -0
- docs/legacy_how_tos/Tools/api-tools.md +29 -0
- docs/legacy_how_tos/Tools/python-tools.md +299 -0
- examples/authentication/aws_authentication.qtype.yaml +63 -0
- examples/conversational_ai/hello_world_chat.qtype.yaml +43 -0
- examples/conversational_ai/simple_chatbot.qtype.yaml +40 -0
- examples/data_processing/batch_processing.qtype.yaml +54 -0
- examples/data_processing/cache_step_results.qtype.yaml +78 -0
- examples/data_processing/collect_results.qtype.yaml +55 -0
- examples/data_processing/dataflow_pipelines.qtype.yaml +108 -0
- examples/data_processing/decode_json.qtype.yaml +23 -0
- examples/data_processing/explode_items.qtype.yaml +25 -0
- examples/data_processing/read_file.qtype.yaml +60 -0
- examples/invoke_models/create_embeddings.qtype.yaml +28 -0
- examples/invoke_models/simple_llm_call.qtype.yaml +32 -0
- examples/language_features/include_raw.qtype.yaml +27 -0
- examples/language_features/ui_hints.qtype.yaml +52 -0
- examples/legacy/bedrock/data_analysis_with_telemetry.qtype.yaml +169 -0
- examples/legacy/bedrock/hello_world.qtype.yaml +39 -0
- examples/legacy/bedrock/hello_world_chat.qtype.yaml +37 -0
- examples/legacy/bedrock/hello_world_chat_with_telemetry.qtype.yaml +40 -0
- examples/legacy/bedrock/hello_world_chat_with_thinking.qtype.yaml +40 -0
- examples/legacy/bedrock/hello_world_completion.qtype.yaml +41 -0
- examples/legacy/bedrock/hello_world_completion_with_auth.qtype.yaml +44 -0
- examples/legacy/bedrock/simple_agent_chat.qtype.yaml +46 -0
- examples/legacy/chat_with_langfuse.qtype.yaml +50 -0
- examples/legacy/data_processor.qtype.yaml +48 -0
- examples/legacy/echo/debug_example.qtype.yaml +59 -0
- examples/legacy/echo/prompt.qtype.yaml +22 -0
- examples/legacy/echo/test.qtype.yaml +26 -0
- examples/legacy/echo/video.qtype.yaml +20 -0
- examples/legacy/field_extractor_example.qtype.yaml +137 -0
- examples/legacy/multi_flow_example.qtype.yaml +125 -0
- examples/legacy/openai/hello_world_chat.qtype.yaml +43 -0
- examples/legacy/openai/hello_world_chat_with_telemetry.qtype.yaml +46 -0
- examples/legacy/rag.qtype.yaml +207 -0
- examples/legacy/time_utilities.qtype.yaml +64 -0
- examples/legacy/vertex/hello_world_chat.qtype.yaml +36 -0
- examples/legacy/vertex/hello_world_completion.qtype.yaml +40 -0
- examples/legacy/vertex/hello_world_completion_with_auth.qtype.yaml +45 -0
- examples/observability_debugging/trace_with_opentelemetry.qtype.yaml +40 -0
- examples/research_assistant/research_assistant.qtype.yaml +94 -0
- examples/research_assistant/tavily.oas.yaml +722 -0
- examples/research_assistant/tavily.qtype.yaml +289 -0
- examples/tutorials/01_hello_world.qtype.yaml +48 -0
- examples/tutorials/02_conversational_chat.qtype.yaml +37 -0
- examples/tutorials/03_structured_data.qtype.yaml +130 -0
- examples/tutorials/04_tools_and_function_calling.qtype.yaml +89 -0
- qtype/application/converters/tools_from_api.py +39 -35
- qtype/base/types.py +6 -1
- qtype/commands/convert.py +3 -6
- qtype/commands/generate.py +7 -3
- qtype/commands/mcp.py +68 -0
- qtype/commands/validate.py +4 -4
- qtype/dsl/custom_types.py +2 -1
- qtype/dsl/linker.py +15 -7
- qtype/dsl/loader.py +3 -3
- qtype/dsl/model.py +24 -3
- qtype/interpreter/api.py +4 -1
- qtype/interpreter/base/base_step_executor.py +3 -1
- qtype/interpreter/conversions.py +7 -3
- qtype/interpreter/executors/construct_executor.py +1 -1
- qtype/interpreter/executors/file_source_executor.py +3 -3
- qtype/interpreter/executors/file_writer_executor.py +4 -4
- qtype/interpreter/executors/index_upsert_executor.py +1 -1
- qtype/interpreter/executors/sql_source_executor.py +1 -1
- qtype/interpreter/resource_cache.py +3 -1
- qtype/interpreter/rich_progress.py +6 -3
- qtype/interpreter/stream/chat/converter.py +25 -17
- qtype/interpreter/stream/chat/ui_request_to_domain_type.py +2 -2
- qtype/interpreter/typing.py +5 -7
- qtype/mcp/__init__.py +0 -0
- qtype/mcp/server.py +467 -0
- qtype/semantic/checker.py +1 -1
- qtype/semantic/generate.py +3 -3
- qtype/semantic/visualize.py +38 -51
- {qtype-0.1.11.dist-info → qtype-0.1.12.dist-info}/METADATA +21 -1
- qtype-0.1.12.dist-info/RECORD +325 -0
- {qtype-0.1.11.dist-info → qtype-0.1.12.dist-info}/WHEEL +1 -1
- schema/qtype.schema.json +4018 -0
- qtype-0.1.11.dist-info/RECORD +0 -142
- {qtype-0.1.11.dist-info → qtype-0.1.12.dist-info}/entry_points.txt +0 -0
- {qtype-0.1.11.dist-info → qtype-0.1.12.dist-info}/licenses/LICENSE +0 -0
- {qtype-0.1.11.dist-info → qtype-0.1.12.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# Mental Model & Philosophy
|
|
2
|
+
|
|
3
|
+
## What is QType?
|
|
4
|
+
|
|
5
|
+
**QType is a domain-specific language (DSL) for rapid prototyping of AI applications.**
|
|
6
|
+
|
|
7
|
+
Qtype is a declarative, text-based language that lets you specify *what* your AI application should do, not *how* to do it. You write YAML specifications that describe flows, steps, models, and data transformations, and QType handles the execution.
|
|
8
|
+
|
|
9
|
+
**Elevator pitch:** QType turns AI application prototypes from days of Python coding into hours of YAML configuration, without sacrificing maintainability or requiring you to learn yet another GUI tool.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Core Mental Model: The Three Primitives
|
|
14
|
+
|
|
15
|
+
Understanding QType requires understanding three core concepts and how they relate:
|
|
16
|
+
|
|
17
|
+
**Think of QType like this:**
|
|
18
|
+
|
|
19
|
+
**Variables** are your data containers (typed boxes)
|
|
20
|
+
**Steps** are your transformations (functions on boxes)
|
|
21
|
+
**Flows** are your pipelines (sequences of transformations)
|
|
22
|
+
**The DSL** is your specification language (what you write)
|
|
23
|
+
**The Semantic layer** is your validator (what checks it)
|
|
24
|
+
**The Interpreter** is your executor (what runs it)
|
|
25
|
+
|
|
26
|
+
**You declare what you want, QType handles how to do it.**
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### 1. Variables: The Data
|
|
30
|
+
|
|
31
|
+
**Variables are typed data containers** that hold values as they move through your application.
|
|
32
|
+
|
|
33
|
+
```yaml
|
|
34
|
+
variables:
|
|
35
|
+
- id: question # A variable named "question"
|
|
36
|
+
type: text # It holds text data
|
|
37
|
+
- id: answer
|
|
38
|
+
type: text
|
|
39
|
+
- id: reviews
|
|
40
|
+
type: list[text] # Can hold complex types like lists
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Key insight:** Variables are *declared* upfront, making data flow explicit before runtime.
|
|
44
|
+
|
|
45
|
+
**Types matter:** Every variable has a type (primitive like `text`/`int`, domain-specific like `ChatMessage`, or custom types you define).
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
### 2. Steps: The Transformations
|
|
50
|
+
|
|
51
|
+
**Steps are individual operations** that take input variables and produce output variables.
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
steps:
|
|
55
|
+
- id: format_prompt
|
|
56
|
+
type: PromptTemplate
|
|
57
|
+
template: "Answer this: {question}"
|
|
58
|
+
inputs:
|
|
59
|
+
- question # Consumes the question variable
|
|
60
|
+
outputs:
|
|
61
|
+
- prompt # Produces a prompt variable
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Each step:**
|
|
65
|
+
- Has a specific type (`PromptTemplate`, `LLMInference`, `InvokeTool`, etc.)
|
|
66
|
+
- Declares which variables it reads (`inputs`)
|
|
67
|
+
- Declares which variables it produces (`outputs`)
|
|
68
|
+
- Performs one focused transformation
|
|
69
|
+
|
|
70
|
+
**Key insight:** Steps are pure transformations. Everything is declared, making flows inspectable and debuggable.
|
|
71
|
+
|
|
72
|
+
**Step types are extensible:** QType ships with ~25 step types (LLMs, tools, data processing, RAG operations), and you can write custom tools for domain-specific operations.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### 3. Flows: The Orchestration
|
|
77
|
+
|
|
78
|
+
**Flows are sequences of steps** that form complete processing pipelines.
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
flows:
|
|
82
|
+
- id: answer_question
|
|
83
|
+
inputs:
|
|
84
|
+
- question # What comes in
|
|
85
|
+
outputs:
|
|
86
|
+
- answer # What goes out
|
|
87
|
+
variables: # All data containers
|
|
88
|
+
- id: question
|
|
89
|
+
type: text
|
|
90
|
+
- id: prompt
|
|
91
|
+
type: text
|
|
92
|
+
- id: answer
|
|
93
|
+
type: text
|
|
94
|
+
steps:
|
|
95
|
+
- id: format_prompt
|
|
96
|
+
type: PromptTemplate
|
|
97
|
+
# ... (transforms question → prompt)
|
|
98
|
+
- id: get_answer
|
|
99
|
+
type: LLMInference
|
|
100
|
+
# ... (transforms prompt → answer)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Flows are data pipelines:**
|
|
104
|
+
- They receive input variables
|
|
105
|
+
- Pass them through a sequence of steps
|
|
106
|
+
- Each step transforms data from one form to another
|
|
107
|
+
- Final outputs are extracted and returned
|
|
108
|
+
|
|
109
|
+
**Key insight:** Flows are *stateless* by default - each execution is independent. Use Memory or external storage for stateful applications (like chatbots). This makes flows easy to reason about, test, and parallelize.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## The Data Flow Model
|
|
114
|
+
|
|
115
|
+
Here's how data moves through a QType application:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
Input Variables
|
|
119
|
+
↓
|
|
120
|
+
Step 1 (transforms A → B)
|
|
121
|
+
↓
|
|
122
|
+
Step 2 (transforms B → C)
|
|
123
|
+
↓
|
|
124
|
+
Step 3 (transforms C → D)
|
|
125
|
+
↓
|
|
126
|
+
Output Variables
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Linear execution:** Steps run sequentially in declaration order. Each step waits for its inputs to be available. Parallelism is supported for multiple inputs.
|
|
130
|
+
|
|
131
|
+
**1-to-many cardinality:** Some steps (like `Explode`) can produce multiple outputs for one input, creating fan-out patterns. Other steps (like `Collect`) aggregate many inputs into one output. This enables batch processing patterns.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Architecture: The Three Layers
|
|
136
|
+
|
|
137
|
+
QType is built in three distinct layers, each with a specific responsibility:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
┌─────────────────────────────────────────────┐
|
|
141
|
+
│ CLI Commands │
|
|
142
|
+
│ (validate, run, serve) │
|
|
143
|
+
├─────────────────────────────────────────────┤
|
|
144
|
+
│ Interpreter │
|
|
145
|
+
│ (execution engine) │
|
|
146
|
+
├─────────────────────────────────────────────┤
|
|
147
|
+
│ Semantic │
|
|
148
|
+
│ (linking & validation) │
|
|
149
|
+
├─────────────────────────────────────────────┤
|
|
150
|
+
│ DSL │
|
|
151
|
+
│ (core data models) │
|
|
152
|
+
└─────────────────────────────────────────────┘
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Layer 1: DSL (Domain-Specific Language)
|
|
156
|
+
|
|
157
|
+
**Responsibility:** Define the data structures that represent QType specifications.
|
|
158
|
+
|
|
159
|
+
- Pure Pydantic models
|
|
160
|
+
- No business logic, just structure
|
|
161
|
+
- Represents YAML as typed Python objects
|
|
162
|
+
- References are strings (like `model: "gpt-4"`)
|
|
163
|
+
|
|
164
|
+
**Example:** The `Flow` model has `steps: list[Step]`, `variables: list[Variable]`, etc.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
### Layer 2: Semantic
|
|
169
|
+
|
|
170
|
+
**Responsibility:** Transform DSL objects into resolved, validated representations.
|
|
171
|
+
|
|
172
|
+
**The pipeline:**
|
|
173
|
+
|
|
174
|
+
1. **Parse** - Load YAML and build DSL objects
|
|
175
|
+
2. **Link** - Resolve string references to actual objects (`"gpt-4"` → `Model` object)
|
|
176
|
+
3. **Resolve** - Build semantic IR (intermediate representation) where all IDs become object references
|
|
177
|
+
4. **Check** - Validate semantic rules (no missing variables, types match, etc.)
|
|
178
|
+
|
|
179
|
+
**Key insight:** This layer catches errors *before* execution. You get fast feedback without running expensive LLM calls.
|
|
180
|
+
|
|
181
|
+
**Symbol table:** During linking, QType builds a map of all components by ID.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
### Layer 3: Interpreter
|
|
186
|
+
|
|
187
|
+
**Responsibility:** Execute flows by running steps with real resources.
|
|
188
|
+
|
|
189
|
+
- Creates executors for each step type
|
|
190
|
+
- Manages resources (models, indexes, caches)
|
|
191
|
+
- Handles streaming and progress tracking
|
|
192
|
+
- Emits telemetry events
|
|
193
|
+
- Orchestrates async execution
|
|
194
|
+
|
|
195
|
+
**Executor pattern:** Each step type has an executor class (`LLMInferenceExecutor`, `InvokeToolExecutor`, etc.) that knows how to run that specific operation. Executors receive `ExecutorContext` with cross-cutting concerns like auth, telemetry, and progress tracking.
|
|
196
|
+
|
|
197
|
+
**Key insight:** The interpreter layer is optional - you could generate code from semantic IR, compile to a different runtime, or build alternative execution strategies. The DSL and semantic layers are independent of execution.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## The Loading Pipeline
|
|
202
|
+
|
|
203
|
+
When you run `qtype validate` or `qtype run`, here's what happens:
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
YAML File
|
|
207
|
+
↓
|
|
208
|
+
1. Load (expand env vars, includes)
|
|
209
|
+
↓
|
|
210
|
+
2. Parse (YAML → DSL models)
|
|
211
|
+
↓
|
|
212
|
+
3. Link (resolve ID references)
|
|
213
|
+
↓
|
|
214
|
+
4. Resolve (DSL → Semantic IR)
|
|
215
|
+
↓
|
|
216
|
+
5. Check (validate semantics)
|
|
217
|
+
↓
|
|
218
|
+
6. Execute (run the flow)
|
|
219
|
+
```
|
|
220
|
+
Each stage builds on the previous, and errors are caught as early as possible.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Philosophy: Why QType Exists
|
|
225
|
+
|
|
226
|
+
### 1. **Code is a Liability**
|
|
227
|
+
|
|
228
|
+
Every line of Python code you write is something you have to maintain, debug, and explain to colleagues. QType shifts complexity from *imperative code* (how to do it) to *declarative specification* (what to do).
|
|
229
|
+
|
|
230
|
+
**Example:** Instead of writing Python to:
|
|
231
|
+
- Initialize an LLM client
|
|
232
|
+
- Format prompts
|
|
233
|
+
- Handle streaming
|
|
234
|
+
- Parse JSON responses
|
|
235
|
+
- Construct typed objects
|
|
236
|
+
- Log telemetry
|
|
237
|
+
|
|
238
|
+
You write YAML that *declares* these operations, and QType handles the implementation.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
### 2. **Modularity and Composability**
|
|
243
|
+
|
|
244
|
+
QType applications are built from composable pieces:
|
|
245
|
+
- **Flows** can invoke other flows
|
|
246
|
+
- **Tools** are reusable functions
|
|
247
|
+
- **Types** define domain models
|
|
248
|
+
- **Models** and **Memories** are shared resources
|
|
249
|
+
|
|
250
|
+
You can build libraries of flows, tools, and types that work together like Lego blocks.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
### 3. **Traceability and Observability**
|
|
255
|
+
|
|
256
|
+
Because everything is declared:
|
|
257
|
+
- You can visualize the entire application structure
|
|
258
|
+
- Trace data flow through the system
|
|
259
|
+
- Emit structured telemetry
|
|
260
|
+
- Understand what's happening without reading code
|
|
261
|
+
|
|
262
|
+
Otel Observability is supported by default.
|
|
263
|
+
|
|
264
|
+
QType makes the *implicit* (hidden in code) *explicit* (visible in YAML).
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
### 4. **Rapid Iteration**
|
|
269
|
+
|
|
270
|
+
Changing a QType application is fast:
|
|
271
|
+
- Edit YAML
|
|
272
|
+
- Validate
|
|
273
|
+
- Run
|
|
274
|
+
|
|
275
|
+
No recompiling, no virtual environment issues, no import errors. The feedback loop is seconds, not minutes.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## What QType Is NOT
|
|
280
|
+
|
|
281
|
+
### ❌ Not a Low-Code/No-Code Tool
|
|
282
|
+
|
|
283
|
+
QType is not Flowise, Dify, LangFlow, or similar GUI-based agent builders.
|
|
284
|
+
|
|
285
|
+
**Why not:**
|
|
286
|
+
- **Audience:** QType targets *engineers* who want text-based specifications they can version control, code review, and integrate into CI/CD
|
|
287
|
+
- **Control:** GUI tools trade precision and flexibility for convenience. QType gives you full control via explicit configuration, and can connect to apis or your code.
|
|
288
|
+
- **Complexity ceiling:** GUIs work great for simple flows but become unwieldy for complex applications with dozens of components. YAML scales better for large systems
|
|
289
|
+
|
|
290
|
+
**When to use GUI tools:** If you're non-technical or building simple demo flows, GUI tools are faster. If you're an engineer building prototype systems, QType is more maintainable.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
### ❌ Not a General Data Engineering Tool
|
|
295
|
+
|
|
296
|
+
**What it is:** QType is not Dagster, Prefect, Airflow, or similar orchestration frameworks.
|
|
297
|
+
|
|
298
|
+
**Why not:**
|
|
299
|
+
- **Focus:** Data engineering tools excel at *data pipelines* (ETL, batch processing, scheduling). QType excels at *AI workflows* (LLM calls, vector search, tool calling, agents)
|
|
300
|
+
- **Features:** Dagster has sophisticated scheduling, retries, dependency management, and data lineage. QType has LLM abstractions, type systems for AI data (ChatMessage, RAGDocument), and streaming support
|
|
301
|
+
- **Overlap:** Both can process data in pipelines, but the primitives are different
|
|
302
|
+
|
|
303
|
+
**When to use data engineering tools:** If your workflow is primarily data transformation, aggregation, and movement without AI components, use Dagster/Airflow. They're better at traditional ETL.
|
|
304
|
+
|
|
305
|
+
**When to use QType:** If your workflow involves LLMs, embeddings, vector search, tool calling, or agents, QType gives you purpose-built primitives. You *could* build these in Dagster, but QType makes it easier.
|
|
306
|
+
|
|
307
|
+
**Can they coexist?** Yes! Use Dagster to orchestrate data pipelines that feed into QType applications, or use QType flows as Dagster ops for AI-specific processing.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## When to Use QType
|
|
312
|
+
|
|
313
|
+
### ✅ Use QType When:
|
|
314
|
+
|
|
315
|
+
**You're prototyping AI applications**
|
|
316
|
+
- Quickly try different LLMs, prompts, and flows
|
|
317
|
+
- Iterate on application structure without Python boilerplate
|
|
318
|
+
- Get validation feedback instantly
|
|
319
|
+
|
|
320
|
+
**You want type-safe AI workflows**
|
|
321
|
+
- Explicit data flow with typed variables
|
|
322
|
+
- Catch errors before runtime
|
|
323
|
+
- Understand what data flows where
|
|
324
|
+
|
|
325
|
+
**You're building modular AI systems**
|
|
326
|
+
- Reusable flows, tools, and types
|
|
327
|
+
- Compose applications from libraries
|
|
328
|
+
- Share components across projects
|
|
329
|
+
|
|
330
|
+
**You value maintainability**
|
|
331
|
+
- YAML specs are easier to review than Python
|
|
332
|
+
- Version control shows exactly what changed
|
|
333
|
+
- Generate documentation automatically
|
|
334
|
+
|
|
335
|
+
**You need observability**
|
|
336
|
+
- Built-in telemetry and tracing
|
|
337
|
+
- Visualize application structure
|
|
338
|
+
- Understand execution patterns
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
### 🤔 Consider Alternatives When:
|
|
343
|
+
|
|
344
|
+
**You need complete Python control**
|
|
345
|
+
- Complex branching logic
|
|
346
|
+
- Dynamic behavior based on runtime conditions
|
|
347
|
+
- Integration with Python-specific libraries
|
|
348
|
+
|
|
349
|
+
**You're building pure data pipelines**
|
|
350
|
+
- No LLM or AI components
|
|
351
|
+
- Traditional ETL operations
|
|
352
|
+
- Dagster/Airflow are better fits
|
|
353
|
+
|
|
354
|
+
**You prefer visual tools**
|
|
355
|
+
- GUI-based development
|
|
356
|
+
- Non-technical users
|
|
357
|
+
- Flowise/Dify are more appropriate
|
|
358
|
+
|
|
359
|
+
**Your workflow is extremely simple**
|
|
360
|
+
- Single LLM call, no orchestration
|
|
361
|
+
- Direct API usage is simpler
|
|
362
|
+
- QType adds unnecessary structure
|
|
363
|
+
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Welcome to the QType development guide! This document provides comprehensive instructions for setting up your development environment and contributing to the project.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Prerequisites](#prerequisites)
|
|
8
|
+
- [Development Environment Setup](#development-environment-setup)
|
|
9
|
+
- [Using QType Commands](#using-qtype-commands)
|
|
10
|
+
- [Running Tests](#running-tests)
|
|
11
|
+
- [Code Quality and Standards](#code-quality-and-standards)
|
|
12
|
+
- [Project Structure](#project-structure)
|
|
13
|
+
- [Making Changes](#making-changes)
|
|
14
|
+
- [Next Steps](#next-steps)
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
- **Python 3.10 or higher** (this project targets Python 3.10+)
|
|
19
|
+
- **uv** package manager (recommended) or **pip**
|
|
20
|
+
- **Git** for version control
|
|
21
|
+
|
|
22
|
+
## Development Environment Setup
|
|
23
|
+
|
|
24
|
+
### 1. Clone the Repository
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git clone https://github.com/yourusername/qtype.git
|
|
28
|
+
cd qtype
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2. Set Up Python Environment
|
|
32
|
+
|
|
33
|
+
We recommend using `uv` for dependency management as it's faster and more reliable:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Install uv if you haven't already
|
|
37
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
38
|
+
|
|
39
|
+
# Install all dependencies, development tools, and qtype in editable mode
|
|
40
|
+
uv sync --extra interpreter --extra mcp
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This single command installs everything you need, including the `qtype` package in editable mode so changes to the source code are immediately reflected.
|
|
44
|
+
|
|
45
|
+
## Using QType Commands
|
|
46
|
+
|
|
47
|
+
After installation, activate the virtual environment:
|
|
48
|
+
```bash
|
|
49
|
+
source ./venv/bin/activate
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
You may see `(qtype)` on yout terminal if you are in bash
|
|
53
|
+
|
|
54
|
+
After installation, you should be able to run the `qtype` command from anywhere:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
qtype --help
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Running Tests
|
|
61
|
+
|
|
62
|
+
The project uses pytest for testing with coverage measurement:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Run all tests
|
|
66
|
+
uv run pytest
|
|
67
|
+
|
|
68
|
+
# Run tests with coverage
|
|
69
|
+
uv run pytest --cov=qtype
|
|
70
|
+
|
|
71
|
+
# Run tests with coverage and generate HTML report
|
|
72
|
+
uv run pytest --cov=qtype --cov-report=html
|
|
73
|
+
|
|
74
|
+
# Run tests with verbose output
|
|
75
|
+
uv run pytest -v
|
|
76
|
+
|
|
77
|
+
# Run specific test file
|
|
78
|
+
uv run pytest tests/test_loader_file_inclusion.py
|
|
79
|
+
|
|
80
|
+
# Run specific test class
|
|
81
|
+
uv run pytest tests/test_loader_file_inclusion.py::TestFileIncludeLoader
|
|
82
|
+
|
|
83
|
+
# Run specific test method
|
|
84
|
+
uv run pytest tests/test_loader_file_inclusion.py::TestFileIncludeLoader::test_include_yaml_file
|
|
85
|
+
|
|
86
|
+
# Run tests matching a pattern
|
|
87
|
+
uv run pytest -k "test_include"
|
|
88
|
+
|
|
89
|
+
# Run tests with specific markers
|
|
90
|
+
uv run pytest -m "not network" # Skip network tests
|
|
91
|
+
uv run pytest -m "not slow" # Skip slow tests
|
|
92
|
+
|
|
93
|
+
# Run tests in parallel (if pytest-xdist is installed)
|
|
94
|
+
uv run pytest -n auto
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Coverage Reports
|
|
98
|
+
|
|
99
|
+
Coverage reports show:
|
|
100
|
+
- Which lines of code are executed during tests
|
|
101
|
+
- Which lines are missing test coverage
|
|
102
|
+
- Overall coverage percentage for each module
|
|
103
|
+
- HTML report with line-by-line coverage highlighting
|
|
104
|
+
|
|
105
|
+
The HTML coverage report (`htmlcov/index.html`) provides the most detailed view, showing exactly which lines need more test coverage.
|
|
106
|
+
|
|
107
|
+
### Test Markers
|
|
108
|
+
|
|
109
|
+
The project uses pytest markers to categorize tests:
|
|
110
|
+
- `@pytest.mark.slow`: Tests that take longer to run
|
|
111
|
+
- `@pytest.mark.network`: Tests requiring network access
|
|
112
|
+
|
|
113
|
+
Skip specific test categories:
|
|
114
|
+
```bash
|
|
115
|
+
# Skip slow tests
|
|
116
|
+
uv run pytest -m "not slow"
|
|
117
|
+
|
|
118
|
+
# Skip network tests
|
|
119
|
+
uv run pytest -m "not network"
|
|
120
|
+
|
|
121
|
+
# Run only network tests
|
|
122
|
+
uv run pytest -m "network"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Code Quality and Standards
|
|
126
|
+
|
|
127
|
+
This project follows strict Python coding standards:
|
|
128
|
+
|
|
129
|
+
### Code Style Requirements
|
|
130
|
+
|
|
131
|
+
- **PEP 8** compliance for all Python code
|
|
132
|
+
- **Type hints** for all function signatures and class attributes
|
|
133
|
+
- **Docstrings** for all public functions, classes, and modules
|
|
134
|
+
- **Clear naming** using snake_case for functions/variables, PascalCase for classes
|
|
135
|
+
- **Line length** limit of 79 characters (as per PEP 8)
|
|
136
|
+
- **f-strings** for string interpolation
|
|
137
|
+
- **Explicit over implicit** code style
|
|
138
|
+
|
|
139
|
+
#### Format code automatically:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Format with ruff
|
|
143
|
+
ruff format qtype/ tests/
|
|
144
|
+
|
|
145
|
+
# Lint with ruff
|
|
146
|
+
ruff check qtype/ tests/
|
|
147
|
+
|
|
148
|
+
# Sort imports
|
|
149
|
+
isort qtype/ tests/
|
|
150
|
+
|
|
151
|
+
# Type checking with mypy
|
|
152
|
+
mypy qtype/ tests/
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### Pre-commit hooks (Optional but recommended):
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
uv pip install pre-commit
|
|
159
|
+
pre-commit install
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Settings are in `.pre-commit-config.yaml`:
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
## Project Structure
|
|
166
|
+
|
|
167
|
+
- `qtype/` – Python package for parsing, validating, and interpreting QType specs
|
|
168
|
+
- `examples/` – Example `.qtype.yaml` specs
|
|
169
|
+
- `schema/` – JSON Schema auto-generated from the DSL
|
|
170
|
+
- `docs/` – Documentation
|
|
171
|
+
- `tests/` – Unit and integration tests
|
|
172
|
+
|
|
173
|
+
## Making Changes
|
|
174
|
+
|
|
175
|
+
### Development Workflow
|
|
176
|
+
|
|
177
|
+
1. **Create a feature branch:**
|
|
178
|
+
```bash
|
|
179
|
+
git checkout -b feature/your-feature-name
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
2. **Make your changes** following the coding standards
|
|
183
|
+
|
|
184
|
+
3. **Write or update tests** for your changes
|
|
185
|
+
|
|
186
|
+
4. **Run tests** to ensure nothing is broken:
|
|
187
|
+
```bash
|
|
188
|
+
uv run pytest --cov=qtype
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
5. **Check code quality:**
|
|
192
|
+
```bash
|
|
193
|
+
ruff format qtype/ tests/
|
|
194
|
+
ruff check qtype/ tests/
|
|
195
|
+
isort qtype/ tests/
|
|
196
|
+
mypy qtype/
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
6. **Test CLI functionality:**
|
|
200
|
+
```bash
|
|
201
|
+
# Generate schema
|
|
202
|
+
ptython -m qtype.cli generate-schema -o schema/test.json
|
|
203
|
+
|
|
204
|
+
# Validate example spec
|
|
205
|
+
ptython -m qtype.cli validate examples/hello_world.qtype.yaml
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
7. **Update documentation** if needed
|
|
209
|
+
|
|
210
|
+
8. **Commit your changes:**
|
|
211
|
+
```bash
|
|
212
|
+
git add .
|
|
213
|
+
git commit -m "feat: add your feature description"
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### How To: Expand The DSL
|
|
217
|
+
|
|
218
|
+
The core of qtype is the DSL specified in [qtype/dsl/model.py](https://github.com/bazaarvoice/qtype/blob/main/qtype/dsl/model.py). All functionality is rooted in the pydantic classes in that file. To expand the dsl with new classes, types, etc., edit this file. If your new class is a subtype (like a Step, etc) you should make sure you update any unions (like `StepType` etc)
|
|
219
|
+
|
|
220
|
+
Once you have it to your liking, you can generate the new schema:
|
|
221
|
+
```
|
|
222
|
+
qtype generate schema -o schema/qtype.schema.json
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
You can make vscode validate it with your newly generated schema by adding it to your `settings.json`:
|
|
226
|
+
```
|
|
227
|
+
"yaml.schemas" : {
|
|
228
|
+
"schema/qtype.schema.json": ["qtype.config.yaml", "*.qtype.yaml"],
|
|
229
|
+
},
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
The semantic version of [qtype/semantic/model.py](https://github.com/bazaarvoice/qtype/blob/main/qtype/semantic/model.py) can also be automatically generated:
|
|
233
|
+
```
|
|
234
|
+
qtype generate semantic-model
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Next, update [qtype/semantic/checker.py](https://github.com/bazaarvoice/qtype/blob/main/qtype/semantic/checker.py) to enforce any semantic rules for your step.
|
|
238
|
+
|
|
239
|
+
Next, make a canonical example of your new type in the `examples` folder (e.g., `examples/new_type_example.qtype.yaml`) and it can be validated:
|
|
240
|
+
```
|
|
241
|
+
qtype validate examples/new_type_example.qtype.yaml
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
The docstrings in the types are used to update the documentation with:
|
|
245
|
+
```
|
|
246
|
+
qtype generate dsl-docs
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Finally, if desired, you can update the interpreter to support your new type. If your new type is a `Step`, you can add an `executor` in the [qtype/interpreter/executors](https://github.com/bazaarvoice/qtype/tree/main/qtype/interpreter/executors) folder and then update the [qtype/interpreter/base/factory.py](https://github.com/bazaarvoice/qtype/blob/main/qtype/interpreter/base/factory.py).
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
### Adding New Dependencies
|
|
253
|
+
|
|
254
|
+
When adding new dependencies, use uv to add to `pyproject.toml`:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
uv add <dependency>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Then update the lock file:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
uv lock
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Next Steps
|
|
267
|
+
|
|
268
|
+
After setting up your development environment:
|
|
269
|
+
|
|
270
|
+
1. Explore the `examples/` directory to understand QType specifications
|
|
271
|
+
2. Run the existing tests to ensure everything works
|
|
272
|
+
3. Read the documentation in `docs/`
|
|
273
|
+
4. Look at open issues for contribution opportunities
|
|
274
|
+
5. Start with small improvements or bug fixes
|
|
275
|
+
|
|
276
|
+
Happy coding! 🚀
|