qtype 0.1.11__py3-none-any.whl → 0.1.13__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/` +0 -0
- qtype/application/__init__.py +0 -2
- qtype/application/converters/tools_from_api.py +67 -57
- qtype/application/converters/tools_from_module.py +66 -32
- qtype/base/types.py +6 -1
- qtype/commands/convert.py +3 -6
- qtype/commands/generate.py +97 -10
- qtype/commands/mcp.py +68 -0
- qtype/commands/run.py +116 -44
- qtype/commands/validate.py +4 -4
- qtype/docs/.pages +8 -0
- qtype/docs/Concepts/mental-model-and-philosophy.md +363 -0
- qtype/docs/Contributing/.pages +4 -0
- qtype/docs/Contributing/index.md +283 -0
- qtype/docs/Contributing/roadmap.md +81 -0
- qtype/docs/Decisions/ADR-001-Chat-vs-Completion-Endpoint-Features.md +56 -0
- qtype/docs/Gallery/dataflow_pipelines.md +81 -0
- qtype/docs/Gallery/dataflow_pipelines.mermaid +45 -0
- qtype/docs/Gallery/research_assistant.md +97 -0
- qtype/docs/Gallery/research_assistant.mermaid +42 -0
- qtype/docs/Gallery/simple_chatbot.md +38 -0
- qtype/docs/Gallery/simple_chatbot.mermaid +35 -0
- qtype/docs/How To/Authentication/configure_aws_authentication.md +60 -0
- qtype/docs/How To/Authentication/use_api_key_authentication.md +40 -0
- qtype/docs/How To/Command Line Usage/load_multiple_inputs_from_files.md +77 -0
- qtype/docs/How To/Command Line Usage/pass_inputs_on_the_cli.md +52 -0
- qtype/docs/How To/Command Line Usage/serve_with_auto_reload.md +27 -0
- qtype/docs/How To/Data Processing/adjust_concurrency.md +40 -0
- qtype/docs/How To/Data Processing/cache_step_results.md +71 -0
- qtype/docs/How To/Data Processing/decode_json_xml.md +24 -0
- qtype/docs/How To/Data Processing/explode_collections.md +40 -0
- qtype/docs/How To/Data Processing/gather_results.md +68 -0
- qtype/docs/How To/Data Processing/invoke_other_flows.md +71 -0
- qtype/docs/How To/Data Processing/load_data_from_athena.md +49 -0
- qtype/docs/How To/Data Processing/read_data_from_files.md +61 -0
- qtype/docs/How To/Data Processing/read_sql_databases.md +46 -0
- qtype/docs/How To/Data Processing/write_data_to_file.md +39 -0
- qtype/docs/How To/Invoke Models/call_large_language_models.md +51 -0
- qtype/docs/How To/Invoke Models/create_embeddings.md +49 -0
- qtype/docs/How To/Invoke Models/reuse_prompts_with_templates.md +38 -0
- qtype/docs/How To/Language Features/include_qtype_yaml.md +45 -0
- qtype/docs/How To/Language Features/include_raw_text_from_other_files.md +48 -0
- qtype/docs/How To/Language Features/reference_entities_by_id.md +51 -0
- qtype/docs/How To/Language Features/use_agent_skills.md +29 -0
- qtype/docs/How To/Language Features/use_environment_variables.md +48 -0
- qtype/docs/How To/Language Features/use_optional_variables.md +42 -0
- qtype/docs/How To/Language Features/use_qtype_mcp.md +59 -0
- qtype/docs/How To/Observability & Debugging/trace_calls_with_open_telemetry.md +49 -0
- qtype/docs/How To/Observability & Debugging/validate_qtype_yaml.md +36 -0
- qtype/docs/How To/Observability & Debugging/visualize_application_architecture.md +61 -0
- qtype/docs/How To/Observability & Debugging/visualize_example.mermaid +35 -0
- qtype/docs/How To/Qtype Server/flow_as_ui.png +0 -0
- qtype/docs/How To/Qtype Server/serve_flows_as_apis.md +40 -0
- qtype/docs/How To/Qtype Server/serve_flows_as_ui.md +41 -0
- qtype/docs/How To/Qtype Server/use_conversational_interfaces.md +56 -0
- qtype/docs/How To/Qtype Server/use_variables_with_ui_hints.md +48 -0
- qtype/docs/How To/Tools & Integration/bind_tool_inputs_and_outputs.md +47 -0
- qtype/docs/How To/Tools & Integration/create_tools_from_openapi_specifications.md +85 -0
- qtype/docs/How To/Tools & Integration/create_tools_from_python_modules.md +87 -0
- qtype/docs/Reference/cli.md +336 -0
- qtype/docs/Reference/plugins.md +99 -0
- qtype/docs/Reference/semantic-validation-rules.md +184 -0
- qtype/docs/Tutorials/.pages +1 -0
- qtype/docs/Tutorials/01-first-qtype-application.md +249 -0
- qtype/docs/Tutorials/02-conversational-chatbot.md +327 -0
- qtype/docs/Tutorials/03-structured-data.md +480 -0
- qtype/docs/Tutorials/04-tools-and-function-calling.md +476 -0
- qtype/docs/Tutorials/example_chat.png +0 -0
- qtype/docs/Tutorials/index.md +92 -0
- qtype/docs/components/APIKeyAuthProvider.md +7 -0
- qtype/docs/components/APITool.md +10 -0
- qtype/docs/components/AWSAuthProvider.md +13 -0
- qtype/docs/components/AWSSecretManager.md +5 -0
- qtype/docs/components/Agent.md +6 -0
- qtype/docs/components/Aggregate.md +7 -0
- qtype/docs/components/AggregateStats.md +7 -0
- qtype/docs/components/Application.md +22 -0
- qtype/docs/components/AuthorizationProvider.md +6 -0
- qtype/docs/components/AuthorizationProviderList.md +5 -0
- qtype/docs/components/BearerTokenAuthProvider.md +6 -0
- qtype/docs/components/BedrockReranker.md +8 -0
- qtype/docs/components/ChatContent.md +7 -0
- qtype/docs/components/ChatMessage.md +6 -0
- qtype/docs/components/Collect.md +6 -0
- qtype/docs/components/ConstantPath.md +5 -0
- qtype/docs/components/Construct.md +6 -0
- qtype/docs/components/CustomType.md +7 -0
- qtype/docs/components/Decoder.md +8 -0
- qtype/docs/components/DecoderFormat.md +8 -0
- qtype/docs/components/DocToTextConverter.md +7 -0
- qtype/docs/components/Document.md +7 -0
- qtype/docs/components/DocumentEmbedder.md +6 -0
- qtype/docs/components/DocumentIndex.md +7 -0
- qtype/docs/components/DocumentSearch.md +7 -0
- qtype/docs/components/DocumentSource.md +12 -0
- qtype/docs/components/DocumentSplitter.md +9 -0
- qtype/docs/components/Echo.md +8 -0
- qtype/docs/components/Embedding.md +7 -0
- qtype/docs/components/EmbeddingModel.md +6 -0
- qtype/docs/components/Explode.md +5 -0
- qtype/docs/components/FieldExtractor.md +21 -0
- qtype/docs/components/FileSource.md +6 -0
- qtype/docs/components/FileWriter.md +7 -0
- qtype/docs/components/Flow.md +14 -0
- qtype/docs/components/FlowInterface.md +7 -0
- qtype/docs/components/Index.md +8 -0
- qtype/docs/components/IndexUpsert.md +6 -0
- qtype/docs/components/InvokeEmbedding.md +7 -0
- qtype/docs/components/InvokeFlow.md +8 -0
- qtype/docs/components/InvokeTool.md +8 -0
- qtype/docs/components/LLMInference.md +9 -0
- qtype/docs/components/ListType.md +5 -0
- qtype/docs/components/Memory.md +8 -0
- qtype/docs/components/MessageRole.md +14 -0
- qtype/docs/components/Model.md +10 -0
- qtype/docs/components/ModelList.md +5 -0
- qtype/docs/components/OAuth2AuthProvider.md +9 -0
- qtype/docs/components/PrimitiveTypeEnum.md +20 -0
- qtype/docs/components/PromptTemplate.md +7 -0
- qtype/docs/components/PythonFunctionTool.md +7 -0
- qtype/docs/components/RAGChunk.md +7 -0
- qtype/docs/components/RAGDocument.md +10 -0
- qtype/docs/components/RAGSearchResult.md +8 -0
- qtype/docs/components/Reranker.md +5 -0
- qtype/docs/components/SQLSource.md +8 -0
- qtype/docs/components/Search.md +7 -0
- qtype/docs/components/SearchResult.md +7 -0
- qtype/docs/components/SecretManager.md +7 -0
- qtype/docs/components/SecretReference.md +7 -0
- qtype/docs/components/Source.md +5 -0
- qtype/docs/components/Step.md +8 -0
- qtype/docs/components/TelemetrySink.md +9 -0
- qtype/docs/components/Tool.md +9 -0
- qtype/docs/components/ToolList.md +5 -0
- qtype/docs/components/TypeList.md +5 -0
- qtype/docs/components/Variable.md +8 -0
- qtype/docs/components/VariableList.md +5 -0
- qtype/docs/components/VectorIndex.md +7 -0
- qtype/docs/components/VectorSearch.md +6 -0
- qtype/docs/components/VertexAuthProvider.md +9 -0
- qtype/docs/components/Writer.md +5 -0
- qtype/docs/example_ui.png +0 -0
- qtype/docs/index.md +81 -0
- qtype/docs/legacy_how_tos/.pages +6 -0
- qtype/docs/legacy_how_tos/Configuration/modular-yaml.md +366 -0
- qtype/docs/legacy_how_tos/Configuration/phoenix_projects.png +0 -0
- qtype/docs/legacy_how_tos/Configuration/phoenix_traces.png +0 -0
- qtype/docs/legacy_how_tos/Configuration/reference-by-id.md +251 -0
- qtype/docs/legacy_how_tos/Configuration/telemetry-setup.md +259 -0
- qtype/docs/legacy_how_tos/Data Types/custom-types.md +52 -0
- qtype/docs/legacy_how_tos/Data Types/domain-types.md +113 -0
- qtype/docs/legacy_how_tos/Debugging/visualize-apps.md +147 -0
- qtype/docs/legacy_how_tos/Tools/api-tools.md +29 -0
- qtype/docs/legacy_how_tos/Tools/python-tools.md +299 -0
- qtype/docs/skills/architect/SKILL.md +188 -0
- qtype/docs/skills/architect/references/cheatsheet.md +198 -0
- qtype/docs/skills/architect/references/patterns.md +29 -0
- qtype/docs/stylesheets/extra.css +27 -0
- qtype/dsl/custom_types.py +2 -1
- qtype/dsl/linker.py +23 -7
- qtype/dsl/loader.py +3 -3
- qtype/dsl/model.py +181 -67
- qtype/examples/authentication/aws_authentication.qtype.yaml +63 -0
- qtype/examples/conversational_ai/hello_world_chat.qtype.yaml +43 -0
- qtype/examples/conversational_ai/simple_chatbot.qtype.yaml +40 -0
- qtype/examples/data_processing/athena_query.qtype.yaml +56 -0
- qtype/examples/data_processing/batch_inputs.csv +5 -0
- qtype/examples/data_processing/batch_processing.qtype.yaml +54 -0
- qtype/examples/data_processing/cache_step_results.qtype.yaml +78 -0
- qtype/examples/data_processing/collect_results.qtype.yaml +55 -0
- qtype/examples/data_processing/create_sample_db.py +129 -0
- qtype/examples/data_processing/dataflow_pipelines.qtype.yaml +108 -0
- qtype/examples/data_processing/decode_json.qtype.yaml +23 -0
- qtype/examples/data_processing/explode_items.qtype.yaml +25 -0
- qtype/examples/data_processing/invoke_other_flows.qtype.yaml +98 -0
- qtype/examples/data_processing/read_file.qtype.yaml +60 -0
- qtype/examples/data_processing/reviews.db +0 -0
- qtype/examples/data_processing/sample_article.txt +1 -0
- qtype/examples/data_processing/sample_documents.jsonl +5 -0
- qtype/examples/invoke_models/create_embeddings.qtype.yaml +28 -0
- qtype/examples/invoke_models/simple_llm_call.qtype.yaml +32 -0
- qtype/examples/language_features/include_raw.qtype.yaml +27 -0
- qtype/examples/language_features/optional_variables.qtype.yaml +32 -0
- qtype/examples/language_features/story_prompt.txt +6 -0
- qtype/examples/language_features/ui_hints.qtype.yaml +52 -0
- qtype/examples/legacy/bedrock/data_analysis_with_telemetry.qtype.yaml +169 -0
- qtype/examples/legacy/bedrock/hello_world.qtype.yaml +39 -0
- qtype/examples/legacy/bedrock/hello_world_chat.qtype.yaml +37 -0
- qtype/examples/legacy/bedrock/hello_world_chat_with_telemetry.qtype.yaml +40 -0
- qtype/examples/legacy/bedrock/hello_world_chat_with_thinking.qtype.yaml +40 -0
- qtype/examples/legacy/bedrock/hello_world_completion.qtype.yaml +41 -0
- qtype/examples/legacy/bedrock/hello_world_completion_with_auth.qtype.yaml +44 -0
- qtype/examples/legacy/bedrock/simple_agent_chat.qtype.yaml +46 -0
- qtype/examples/legacy/chat_with_langfuse.qtype.yaml +50 -0
- qtype/examples/legacy/data/customers.csv +6 -0
- qtype/examples/legacy/data_processor.qtype.yaml +48 -0
- qtype/examples/legacy/echo/debug_example.qtype.yaml +59 -0
- qtype/examples/legacy/echo/prompt.qtype.yaml +22 -0
- qtype/examples/legacy/echo/readme.md +29 -0
- qtype/examples/legacy/echo/test.qtype.yaml +26 -0
- qtype/examples/legacy/echo/video.qtype.yaml +20 -0
- qtype/examples/legacy/field_extractor_example.qtype.yaml +137 -0
- qtype/examples/legacy/multi_flow_example.qtype.yaml +125 -0
- qtype/examples/legacy/openai/hello_world_chat.qtype.yaml +43 -0
- qtype/examples/legacy/openai/hello_world_chat_with_telemetry.qtype.yaml +46 -0
- qtype/examples/legacy/qtype_plugin_example.py +51 -0
- qtype/examples/legacy/rag.qtype.yaml +207 -0
- qtype/examples/legacy/sample_data.txt +43 -0
- qtype/examples/legacy/time_utilities.qtype.yaml +64 -0
- qtype/examples/legacy/vertex/README.md +11 -0
- qtype/examples/legacy/vertex/hello_world_chat.qtype.yaml +36 -0
- qtype/examples/legacy/vertex/hello_world_completion.qtype.yaml +40 -0
- qtype/examples/legacy/vertex/hello_world_completion_with_auth.qtype.yaml +45 -0
- qtype/examples/observability_debugging/trace_with_opentelemetry.qtype.yaml +40 -0
- qtype/examples/research_assistant/research_assistant.qtype.yaml +94 -0
- qtype/examples/research_assistant/tavily.oas.yaml +722 -0
- qtype/examples/research_assistant/tavily.qtype.yaml +216 -0
- qtype/examples/tutorials/01_hello_world.qtype.yaml +48 -0
- qtype/examples/tutorials/02_conversational_chat.qtype.yaml +37 -0
- qtype/examples/tutorials/03_structured_data.qtype.yaml +130 -0
- qtype/examples/tutorials/04_tools_and_function_calling.qtype.yaml +89 -0
- qtype/interpreter/api.py +4 -1
- qtype/interpreter/base/base_step_executor.py +3 -1
- qtype/interpreter/base/stream_emitter.py +19 -13
- qtype/interpreter/conversions.py +7 -3
- qtype/interpreter/converters.py +142 -26
- qtype/interpreter/executors/agent_executor.py +2 -3
- qtype/interpreter/executors/aggregate_executor.py +3 -4
- qtype/interpreter/executors/construct_executor.py +15 -15
- qtype/interpreter/executors/doc_to_text_executor.py +1 -3
- qtype/interpreter/executors/field_extractor_executor.py +13 -12
- qtype/interpreter/executors/file_source_executor.py +21 -34
- qtype/interpreter/executors/file_writer_executor.py +4 -4
- qtype/interpreter/executors/index_upsert_executor.py +1 -1
- qtype/interpreter/executors/invoke_embedding_executor.py +1 -4
- qtype/interpreter/executors/invoke_flow_executor.py +2 -2
- qtype/interpreter/executors/invoke_tool_executor.py +19 -18
- qtype/interpreter/executors/llm_inference_executor.py +16 -18
- qtype/interpreter/executors/prompt_template_executor.py +1 -3
- 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/tools/function_tool_helper.py +11 -10
- qtype/interpreter/types.py +89 -4
- qtype/interpreter/typing.py +35 -38
- qtype/mcp/__init__.py +0 -0
- qtype/mcp/server.py +722 -0
- qtype/schema/qtype.schema.json +4016 -0
- qtype/semantic/checker.py +20 -1
- qtype/semantic/generate.py +6 -9
- qtype/semantic/model.py +26 -33
- qtype/semantic/resolver.py +7 -0
- qtype/semantic/visualize.py +45 -53
- {qtype-0.1.11.dist-info → qtype-0.1.13.dist-info}/METADATA +65 -44
- qtype-0.1.13.dist-info/RECORD +352 -0
- {qtype-0.1.11.dist-info → qtype-0.1.13.dist-info}/WHEEL +1 -2
- qtype/application/facade.py +0 -177
- qtype-0.1.11.dist-info/RECORD +0 -142
- qtype-0.1.11.dist-info/top_level.txt +0 -1
- {qtype-0.1.11.dist-info → qtype-0.1.13.dist-info}/entry_points.txt +0 -0
- {qtype-0.1.11.dist-info → qtype-0.1.13.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
# Working with Types and Structured Data
|
|
2
|
+
|
|
3
|
+
**Time:** 25 minutes
|
|
4
|
+
**Prerequisites:** [Tutorial 1: Your First QType Application](01-first-qtype-application.md)
|
|
5
|
+
**Example:** [`03_structured_data.qtype.yaml`](https://github.com/bazaarvoice/qtype/blob/main/examples/tutorials/03_structured_data.qtype.yaml)
|
|
6
|
+
|
|
7
|
+
**What you'll learn:**
|
|
8
|
+
|
|
9
|
+
* Define custom types for your domain
|
|
10
|
+
* Parse LLM JSON responses into structured data
|
|
11
|
+
* Build typed objects from extracted fields
|
|
12
|
+
* Work with list types
|
|
13
|
+
|
|
14
|
+
**What you'll build:** An application that analyzes product reviews and extracts structured sentiment data including ratings, confidence scores, and key points.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Background: Why Custom Types?
|
|
19
|
+
|
|
20
|
+
So far you've worked with simple `text` types. But real applications need structure:
|
|
21
|
+
|
|
22
|
+
- **Domain models** - Product reviews, user profiles, search results
|
|
23
|
+
- **Validation** - Ensure data has required fields
|
|
24
|
+
- **Type safety** - Catch errors before runtime
|
|
25
|
+
- **Composability** - Build complex types from simpler ones
|
|
26
|
+
|
|
27
|
+
QType lets you define **CustomTypes** to model your domain, just like you'd define classes in Python.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Part 1: Define Your Custom Type (5 minutes)
|
|
32
|
+
|
|
33
|
+
### Create Your Application File
|
|
34
|
+
|
|
35
|
+
Create `03_structured_data.qtype.yaml`:
|
|
36
|
+
|
|
37
|
+
```yaml
|
|
38
|
+
id: review_sentiment_analyzer
|
|
39
|
+
description: |
|
|
40
|
+
Analyzes a product review to extract structured sentiment insights.
|
|
41
|
+
Demonstrates custom types and structured data extraction.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
### Define a CustomType
|
|
47
|
+
|
|
48
|
+
Before the `models:` section, add a `types:` section:
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
types:
|
|
52
|
+
- id: ReviewSentiment
|
|
53
|
+
description: Structured sentiment analysis of a review
|
|
54
|
+
properties:
|
|
55
|
+
sentiment: text
|
|
56
|
+
confidence: float
|
|
57
|
+
key_points: list[text]
|
|
58
|
+
rating: int
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**What this means:**
|
|
62
|
+
|
|
63
|
+
**`types:` section** - Where you define custom data structures
|
|
64
|
+
|
|
65
|
+
**`properties:`** - The fields your type contains:
|
|
66
|
+
- `sentiment: text` - A simple text field
|
|
67
|
+
- `confidence: float` - A decimal number (0.0-1.0)
|
|
68
|
+
- `key_points: list[text]` - A list of strings (new!)
|
|
69
|
+
- `rating: int` - An integer (1-5 star rating)
|
|
70
|
+
|
|
71
|
+
**List types** use the syntax `list[element_type]`. Examples:
|
|
72
|
+
- `list[text]` - List of strings
|
|
73
|
+
- `list[int]` - List of integers
|
|
74
|
+
- `list[ReviewSentiment]` - List of custom types
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### Add Model Configuration
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
models:
|
|
82
|
+
- type: Model
|
|
83
|
+
id: analyzer_model
|
|
84
|
+
provider: aws-bedrock
|
|
85
|
+
model_id: amazon.nova-lite-v1:0
|
|
86
|
+
inference_params:
|
|
87
|
+
temperature: 0.7
|
|
88
|
+
max_tokens: 512
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Check your work:**
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
qtype validate 03_structured_data.qtype.yaml
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Should pass ✅
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Part 2: Build the Analysis Flow (10 minutes)
|
|
102
|
+
|
|
103
|
+
### Define Flow Variables
|
|
104
|
+
|
|
105
|
+
Add the flow structure:
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
flows:
|
|
109
|
+
- id: analyze_review
|
|
110
|
+
description: Analyzes a single review and extracts structured sentiment
|
|
111
|
+
inputs:
|
|
112
|
+
- review_text
|
|
113
|
+
outputs:
|
|
114
|
+
- result
|
|
115
|
+
|
|
116
|
+
variables:
|
|
117
|
+
- id: review_text
|
|
118
|
+
type: text
|
|
119
|
+
- id: raw_llm_response
|
|
120
|
+
type: text
|
|
121
|
+
- id: llm_response
|
|
122
|
+
type: text
|
|
123
|
+
- id: sentiment
|
|
124
|
+
type: text
|
|
125
|
+
- id: confidence
|
|
126
|
+
type: float
|
|
127
|
+
- id: key_points
|
|
128
|
+
type: list[text]
|
|
129
|
+
- id: rating
|
|
130
|
+
type: int
|
|
131
|
+
- id: result
|
|
132
|
+
type: ReviewSentiment
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**What's new:**
|
|
136
|
+
|
|
137
|
+
**Multiple variable types** - Notice we have:
|
|
138
|
+
- Simple types (`text`, `float`, `int`)
|
|
139
|
+
- List type (`list[text]`)
|
|
140
|
+
- Custom type (`ReviewSentiment`)
|
|
141
|
+
|
|
142
|
+
**Why so many variables?** Each step transforms data from one form to another. This explicit data flow makes debugging easier and documents how information moves through your application.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### Step 1: Create the Analysis Prompt
|
|
147
|
+
|
|
148
|
+
Add the first step under `steps:`:
|
|
149
|
+
|
|
150
|
+
```yaml
|
|
151
|
+
steps:
|
|
152
|
+
# Step 1: Create analysis prompt
|
|
153
|
+
- id: analysis_prompt
|
|
154
|
+
type: PromptTemplate
|
|
155
|
+
template: |
|
|
156
|
+
Analyze this product review and extract structured information.
|
|
157
|
+
|
|
158
|
+
Review: {{review_text}}
|
|
159
|
+
|
|
160
|
+
Respond with ONLY valid JSON, no other text or markdown. Use this exact structure:
|
|
161
|
+
{{{{
|
|
162
|
+
"sentiment": "positive|negative|neutral|mixed",
|
|
163
|
+
"confidence": 0.95,
|
|
164
|
+
"key_points": ["point 1", "point 2"],
|
|
165
|
+
"rating": 4
|
|
166
|
+
}}}}
|
|
167
|
+
|
|
168
|
+
Where:
|
|
169
|
+
- sentiment: overall sentiment (positive/negative/neutral/mixed)
|
|
170
|
+
- confidence: your confidence score (0.0-1.0)
|
|
171
|
+
- key_points: 2-3 main points from the review
|
|
172
|
+
- rating: estimated star rating 1-5 based on the tone
|
|
173
|
+
|
|
174
|
+
Return ONLY the JSON object, nothing else.
|
|
175
|
+
inputs:
|
|
176
|
+
- review_text
|
|
177
|
+
outputs:
|
|
178
|
+
- raw_llm_response
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Key technique - Escaping braces:**
|
|
182
|
+
|
|
183
|
+
Notice `{{` and `}}` in the template? QType uses Python's `.format()` method where `{variable}` is a placeholder. To include literal curly braces in the output, you must double them:
|
|
184
|
+
- `{{` → outputs `{`
|
|
185
|
+
- `}}` → outputs `}`
|
|
186
|
+
|
|
187
|
+
So to output the JSON structure, we use `{{ ... }}` which renders as `{ ... }` in the actual prompt.
|
|
188
|
+
|
|
189
|
+
**Why "ONLY valid JSON"?** LLMs often add explanatory text or wrap JSON in markdown code fences. Being explicit reduces these issues.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
### Step 2: Run LLM Inference
|
|
194
|
+
|
|
195
|
+
```yaml
|
|
196
|
+
# Step 2: Run LLM inference
|
|
197
|
+
- id: analyze
|
|
198
|
+
type: LLMInference
|
|
199
|
+
model: analyzer_model
|
|
200
|
+
inputs:
|
|
201
|
+
- raw_llm_response
|
|
202
|
+
outputs:
|
|
203
|
+
- llm_response
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**LLMInference step** sends the prompt to your model and returns the response as text. Simple and familiar from Tutorial 1.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### Step 3: Parse JSON with Decoder
|
|
211
|
+
|
|
212
|
+
Here's the new step type:
|
|
213
|
+
|
|
214
|
+
```yaml
|
|
215
|
+
# Step 3: Parse the JSON response and build the ReviewSentiment object
|
|
216
|
+
# Decoder converts the JSON string into structured data
|
|
217
|
+
- id: parse_and_build
|
|
218
|
+
type: Decoder
|
|
219
|
+
format: json
|
|
220
|
+
inputs:
|
|
221
|
+
- llm_response
|
|
222
|
+
outputs:
|
|
223
|
+
- sentiment
|
|
224
|
+
- confidence
|
|
225
|
+
- key_points
|
|
226
|
+
- rating
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**What Decoder does:**
|
|
230
|
+
|
|
231
|
+
**`format: json`** - Tells QType to parse as JSON (also supports `xml`)
|
|
232
|
+
|
|
233
|
+
**Multiple outputs** - Each output name must match a field in the JSON:
|
|
234
|
+
```json
|
|
235
|
+
{
|
|
236
|
+
"sentiment": "positive", ← goes to sentiment variable
|
|
237
|
+
"confidence": 0.95, ← goes to confidence variable
|
|
238
|
+
"key_points": [...], ← goes to key_points variable
|
|
239
|
+
"rating": 4 ← goes to rating variable
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Smart parsing:**
|
|
244
|
+
- Automatically strips markdown code fences (````json`)
|
|
245
|
+
- Validates JSON syntax
|
|
246
|
+
- Maps JSON types to QType types (string→text, number→float/int, array→list)
|
|
247
|
+
- Raises clear errors if fields are missing or malformed
|
|
248
|
+
|
|
249
|
+
**Check your work:**
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
qtype validate 03_structured_data.qtype.yaml
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
### Step 4: Construct the Typed Object
|
|
258
|
+
|
|
259
|
+
Final step - convert individual fields into your custom type:
|
|
260
|
+
|
|
261
|
+
```yaml
|
|
262
|
+
# Step 4: Construct a ReviewSentiment object
|
|
263
|
+
# Construct builds typed objects from the decoded fields
|
|
264
|
+
- id: build_result
|
|
265
|
+
type: Construct
|
|
266
|
+
output_type: ReviewSentiment
|
|
267
|
+
field_bindings:
|
|
268
|
+
sentiment: sentiment
|
|
269
|
+
confidence: confidence
|
|
270
|
+
key_points: key_points
|
|
271
|
+
rating: rating
|
|
272
|
+
inputs:
|
|
273
|
+
- sentiment
|
|
274
|
+
- confidence
|
|
275
|
+
- key_points
|
|
276
|
+
- rating
|
|
277
|
+
outputs:
|
|
278
|
+
- result
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**What Construct does:**
|
|
282
|
+
|
|
283
|
+
**`output_type: ReviewSentiment`** - Specifies which custom type to build
|
|
284
|
+
|
|
285
|
+
**`field_bindings:`** - Maps type field names to input variables:
|
|
286
|
+
```yaml
|
|
287
|
+
field_bindings:
|
|
288
|
+
<property_name>: <variable_name>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
In this case, names match (`sentiment: sentiment`), but you could use different names:
|
|
292
|
+
```yaml
|
|
293
|
+
field_bindings:
|
|
294
|
+
sentiment: analyzed_sentiment # Maps analyzed_sentiment variable to sentiment property
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Why Construct?** It validates that:
|
|
298
|
+
- All required properties are provided
|
|
299
|
+
- Types match (float for confidence, int for rating, etc.)
|
|
300
|
+
- The result is a valid `ReviewSentiment` instance
|
|
301
|
+
|
|
302
|
+
This catches errors early rather than failing later in your application.
|
|
303
|
+
|
|
304
|
+
**Final validation:**
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
qtype validate 03_structured_data.qtype.yaml
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Should pass ✅
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Part 3: Test Your Application (5 minutes)
|
|
315
|
+
|
|
316
|
+
### Run It!
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
qtype run -i '{"review_text":"These headphones are amazing! Great sound quality and super comfortable. Battery lasts all day."}' 03_structured_data.qtype.yaml
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Expected output:**
|
|
323
|
+
|
|
324
|
+
```json
|
|
325
|
+
{
|
|
326
|
+
"result": {
|
|
327
|
+
"sentiment": "positive",
|
|
328
|
+
"confidence": 0.95,
|
|
329
|
+
"key_points": [
|
|
330
|
+
"Great sound quality",
|
|
331
|
+
"Super comfortable",
|
|
332
|
+
"Long battery life"
|
|
333
|
+
],
|
|
334
|
+
"rating": 5
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
### Try Different Reviews
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
# Negative review
|
|
345
|
+
qtype run -i '{"review_text":"Terrible product. Broke after one week and customer service was unhelpful."}' 03_structured_data.qtype.yaml
|
|
346
|
+
|
|
347
|
+
# Mixed review
|
|
348
|
+
qtype run -i '{"review_text":"Good sound but uncomfortable after an hour. Battery is okay but not great."}' 03_structured_data.qtype.yaml
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Notice how the LLM adapts its analysis while maintaining the structured format!
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## Part 4: Understanding the Data Flow (5 minutes)
|
|
356
|
+
|
|
357
|
+
### The Complete Pipeline
|
|
358
|
+
|
|
359
|
+
Here's what happens when you run the application:
|
|
360
|
+
|
|
361
|
+
```
|
|
362
|
+
1. User Input (text)
|
|
363
|
+
"These headphones are amazing!"
|
|
364
|
+
↓
|
|
365
|
+
|
|
366
|
+
2. PromptTemplate
|
|
367
|
+
Creates prompt with JSON format instructions
|
|
368
|
+
↓
|
|
369
|
+
|
|
370
|
+
3. LLMInference
|
|
371
|
+
Sends to model → Returns JSON string
|
|
372
|
+
↓
|
|
373
|
+
|
|
374
|
+
4. Decoder
|
|
375
|
+
Parses JSON string → Extracts individual fields
|
|
376
|
+
{sentiment: "positive", confidence: 0.95, ...}
|
|
377
|
+
↓
|
|
378
|
+
|
|
379
|
+
5. Construct
|
|
380
|
+
Builds ReviewSentiment object from fields
|
|
381
|
+
ReviewSentiment(sentiment="positive", confidence=0.95, ...)
|
|
382
|
+
↓
|
|
383
|
+
|
|
384
|
+
6. Output (ReviewSentiment)
|
|
385
|
+
Validated, typed data ready for downstream use
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
**Key insight:** Each step has a single, focused responsibility:
|
|
389
|
+
- **PromptTemplate** - Format instructions
|
|
390
|
+
- **LLMInference** - Get AI response
|
|
391
|
+
- **Decoder** - Parse structured data
|
|
392
|
+
- **Construct** - Validate and type
|
|
393
|
+
|
|
394
|
+
This separation makes each step testable and reusable.
|
|
395
|
+
|
|
396
|
+
**Note:** You could simplify this by having the LLM return `{"result": {...}}` and using Decoder to output directly to a `ReviewSentiment` variable, skipping the Construct step. However, this tutorial demonstrates both steps separately so you understand when to use each:
|
|
397
|
+
- **Decoder** - When you need to parse text and extract individual fields
|
|
398
|
+
- **Construct** - When you need to build typed objects from already-extracted data
|
|
399
|
+
|
|
400
|
+
In practice, use the approach that best fits your use case.
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
### Error Handling
|
|
405
|
+
|
|
406
|
+
What happens if the LLM returns invalid JSON?
|
|
407
|
+
|
|
408
|
+
**Decoder will fail** with a clear error:
|
|
409
|
+
```
|
|
410
|
+
Invalid JSON input: Expecting ',' delimiter: line 2 column 5 (char 45)
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
**What if a field is missing?**
|
|
414
|
+
```
|
|
415
|
+
Output variable 'confidence' not found in decoded result
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**What if a type is wrong?**
|
|
419
|
+
```
|
|
420
|
+
Cannot construct ReviewSentiment: field 'rating' expects int, got str
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
These explicit errors help you debug issues quickly. In production, you might add retry logic or fallback values.
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## What You've Learned
|
|
428
|
+
|
|
429
|
+
Congratulations! You've mastered:
|
|
430
|
+
|
|
431
|
+
✅ **CustomType definition** - Modeling your domain with structured types
|
|
432
|
+
✅ **List types** - Working with `list[text]` and other collections
|
|
433
|
+
✅ **Decoder step** - Parsing JSON into individual typed fields
|
|
434
|
+
✅ **Construct step** - Building validated custom type instances
|
|
435
|
+
✅ **Field Bindings** - Connecting variables to type properties
|
|
436
|
+
✅ **Type safety** - Catching errors early with validation
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## Next Steps
|
|
441
|
+
|
|
442
|
+
**Reference the complete example:**
|
|
443
|
+
|
|
444
|
+
- [`03_structured_data.qtype.yaml`](https://github.com/bazaarvoice/qtype/blob/main/examples/tutorials/03_structured_data.qtype.yaml) - Full working example
|
|
445
|
+
|
|
446
|
+
**Learn more:**
|
|
447
|
+
|
|
448
|
+
- [Tutorial: Tools and Function Calling](04-tools-and-function-calling.md)
|
|
449
|
+
- [CustomType Reference](../components/CustomType.md)
|
|
450
|
+
- [Decoder Reference](../components/Decoder.md)
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## Common Questions
|
|
455
|
+
|
|
456
|
+
**Q: Can I nest custom types?**
|
|
457
|
+
A: Yes! A CustomType property can be another CustomType:
|
|
458
|
+
```yaml
|
|
459
|
+
types:
|
|
460
|
+
- id: Address
|
|
461
|
+
properties:
|
|
462
|
+
street: text
|
|
463
|
+
city: text
|
|
464
|
+
- id: User
|
|
465
|
+
properties:
|
|
466
|
+
name: text
|
|
467
|
+
address: Address # Nested custom type
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
**Q: What if the LLM returns extra fields not in my type?**
|
|
471
|
+
A: Extra fields are ignored. Decoder only extracts the fields you've specified in `outputs:`.
|
|
472
|
+
|
|
473
|
+
**Q: Can Decoder output the entire JSON as one variable?**
|
|
474
|
+
A: Not directly. Decoder maps JSON fields to individual outputs. If you need the whole JSON, use `type: any` in your variable and skip Decoder.
|
|
475
|
+
|
|
476
|
+
**Q: When should I use Decoder vs FieldExtractor?**
|
|
477
|
+
A: Use **Decoder** when you have a JSON/XML string to parse. Use **FieldExtractor** when you already have structured data and need to extract specific fields using JSONPath (covered in advanced tutorials).
|
|
478
|
+
|
|
479
|
+
**Q: Can I make properties optional?**
|
|
480
|
+
A: Yes! Mark variables as optional using the `?` suffix (e.g., `type: text?`). Optional variables can be unset, `None`, or have a value. This is useful when extracting fields that may not always be present. See [Use Optional Variables](../How%20To/Language%20Features/use_optional_variables.md).
|