mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-05-29 17:25:15 +02:00
Update flow parameter tech spec for advanced params (#537)
* Add advanced mode to tech spec, fix enum description in tech spec * Updated tech-spec for controlled-by relationship between parameters * Update tg-show-flows CLI * Update tg-show-flows, tg-show-flow-classes, tg-start-flow CLI * Add tg-show-parameter-types
This commit is contained in:
parent
8929a680a1
commit
8354ea1276
5 changed files with 311 additions and 50 deletions
|
|
@ -100,7 +100,24 @@ Parameter definitions are stored centrally in the schema and config system with
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "LLM model to use",
|
"description": "LLM model to use",
|
||||||
"default": "gpt-4",
|
"default": "gpt-4",
|
||||||
"enum": ["gpt-4", "gpt-3.5-turbo", "claude-3", "gemma3:8b"],
|
"enum": [
|
||||||
|
{
|
||||||
|
"id": "gpt-4",
|
||||||
|
"description": "OpenAI GPT-4 (Most Capable)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gpt-3.5-turbo",
|
||||||
|
"description": "OpenAI GPT-3.5 Turbo (Fast & Efficient)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "claude-3",
|
||||||
|
"description": "Anthropic Claude 3 (Thoughtful & Safe)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gemma3:8b",
|
||||||
|
"description": "Google Gemma 3 8B (Open Source)"
|
||||||
|
}
|
||||||
|
],
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"model-size": {
|
"model-size": {
|
||||||
|
|
@ -137,25 +154,36 @@ Flow classes define parameter metadata with type references, descriptions, and o
|
||||||
{
|
{
|
||||||
"flow_class": "document-analysis",
|
"flow_class": "document-analysis",
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"model": {
|
"llm-model": {
|
||||||
"type": "llm-model",
|
"type": "llm-model",
|
||||||
"description": "LLM model to use for document analysis",
|
"description": "Primary LLM model for text completion",
|
||||||
"order": 1
|
"order": 1
|
||||||
},
|
},
|
||||||
"size": {
|
"llm-rag-model": {
|
||||||
"type": "model-size",
|
"type": "llm-model",
|
||||||
"description": "Model size variant to use",
|
"description": "LLM model for RAG operations",
|
||||||
"order": 2
|
"order": 2,
|
||||||
|
"advanced": true,
|
||||||
|
"controlled-by": "llm-model"
|
||||||
},
|
},
|
||||||
"temp": {
|
"llm-temperature": {
|
||||||
"type": "temperature",
|
"type": "temperature",
|
||||||
"description": "Generation temperature for creativity control",
|
"description": "Generation temperature for creativity control",
|
||||||
"order": 3
|
"order": 3,
|
||||||
|
"advanced": true
|
||||||
},
|
},
|
||||||
"chunk": {
|
"chunk-size": {
|
||||||
"type": "chunk-size",
|
"type": "chunk-size",
|
||||||
"description": "Document chunk size for processing",
|
"description": "Document chunk size for processing",
|
||||||
"order": 4
|
"order": 4,
|
||||||
|
"advanced": true
|
||||||
|
},
|
||||||
|
"chunk-overlap": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Overlap between document chunks",
|
||||||
|
"order": 5,
|
||||||
|
"advanced": true,
|
||||||
|
"controlled-by": "chunk-size"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"class": {
|
"class": {
|
||||||
|
|
@ -163,8 +191,16 @@ Flow classes define parameter metadata with type references, descriptions, and o
|
||||||
"request": "non-persistent://tg/request/text-completion:{class}",
|
"request": "non-persistent://tg/request/text-completion:{class}",
|
||||||
"response": "non-persistent://tg/response/text-completion:{class}",
|
"response": "non-persistent://tg/response/text-completion:{class}",
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"model": "{model}",
|
"model": "{llm-model}",
|
||||||
"temperature": "{temp}"
|
"temperature": "{llm-temperature}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rag-completion:{class}": {
|
||||||
|
"request": "non-persistent://tg/request/rag-completion:{class}",
|
||||||
|
"response": "non-persistent://tg/response/rag-completion:{class}",
|
||||||
|
"parameters": {
|
||||||
|
"model": "{llm-rag-model}",
|
||||||
|
"temperature": "{llm-temperature}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -173,8 +209,8 @@ Flow classes define parameter metadata with type references, descriptions, and o
|
||||||
"input": "persistent://tg/flow/chunk:{id}",
|
"input": "persistent://tg/flow/chunk:{id}",
|
||||||
"output": "persistent://tg/flow/chunk-load:{id}",
|
"output": "persistent://tg/flow/chunk-load:{id}",
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"chunk_size": "{chunk}",
|
"chunk_size": "{chunk-size}",
|
||||||
"chunk_overlap": 100
|
"chunk_overlap": "{chunk-overlap}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -185,6 +221,8 @@ The `parameters` section maps flow-specific parameter names (keys) to parameter
|
||||||
- `type`: Reference to centrally-defined parameter definition (e.g., "llm-model")
|
- `type`: Reference to centrally-defined parameter definition (e.g., "llm-model")
|
||||||
- `description`: Human-readable description for UI display
|
- `description`: Human-readable description for UI display
|
||||||
- `order`: Display order for parameter forms (lower numbers appear first)
|
- `order`: Display order for parameter forms (lower numbers appear first)
|
||||||
|
- `advanced` (optional): Boolean flag indicating if this is an advanced parameter (default: false). When set to true, the UI may hide this parameter by default or place it in an "Advanced" section
|
||||||
|
- `controlled-by` (optional): Name of another parameter that controls this parameter's value when in simple mode. When specified, this parameter inherits its value from the controlling parameter unless explicitly overridden
|
||||||
|
|
||||||
This approach allows:
|
This approach allows:
|
||||||
- Reusable parameter type definitions across multiple flow classes
|
- Reusable parameter type definitions across multiple flow classes
|
||||||
|
|
@ -193,6 +231,8 @@ This approach allows:
|
||||||
- Enhanced UI experience with descriptive parameter forms
|
- Enhanced UI experience with descriptive parameter forms
|
||||||
- Consistent parameter validation across flows
|
- Consistent parameter validation across flows
|
||||||
- Easy addition of new standard parameter types
|
- Easy addition of new standard parameter types
|
||||||
|
- Simplified UI with basic/advanced mode separation
|
||||||
|
- Parameter value inheritance for related settings
|
||||||
|
|
||||||
#### Flow Launch Request
|
#### Flow Launch Request
|
||||||
|
|
||||||
|
|
@ -203,32 +243,62 @@ The flow launch API accepts parameters using the flow's parameter names:
|
||||||
"flow_class": "document-analysis",
|
"flow_class": "document-analysis",
|
||||||
"flow_id": "customer-A-flow",
|
"flow_id": "customer-A-flow",
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"model": "claude-3",
|
"llm-model": "claude-3",
|
||||||
"size": "12b",
|
"llm-temperature": 0.5,
|
||||||
"temp": 0.5,
|
"chunk-size": 1024
|
||||||
"chunk": 1024
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note: In this example, `llm-rag-model` is not explicitly provided but will inherit the value "claude-3" from `llm-model` due to its `controlled-by` relationship. Similarly, `chunk-overlap` could inherit a calculated value based on `chunk-size`.
|
||||||
|
|
||||||
The system will:
|
The system will:
|
||||||
1. Extract parameter metadata from flow class definition
|
1. Extract parameter metadata from flow class definition
|
||||||
2. Map flow parameter names to their type definitions (e.g., `model` → `llm-model` type)
|
2. Map flow parameter names to their type definitions (e.g., `llm-model` → `llm-model` type)
|
||||||
3. Validate user-provided values against the parameter type definitions
|
3. Resolve controlled-by relationships (e.g., `llm-rag-model` inherits from `llm-model`)
|
||||||
4. Substitute validated values into processor parameters during flow instantiation
|
4. Validate user-provided and inherited values against the parameter type definitions
|
||||||
|
5. Substitute resolved values into processor parameters during flow instantiation
|
||||||
|
|
||||||
### Implementation Details
|
### Implementation Details
|
||||||
|
|
||||||
#### Parameter Resolution Process
|
#### Parameter Resolution Process
|
||||||
|
|
||||||
1. **Flow Class Loading**: Load flow class and extract parameter metadata
|
1. **Flow Class Loading**: Load flow class and extract parameter metadata
|
||||||
2. **Metadata Extraction**: Extract `type`, `description`, and `order` for each parameter
|
2. **Metadata Extraction**: Extract `type`, `description`, `order`, `advanced`, and `controlled-by` for each parameter
|
||||||
3. **Type Definition Lookup**: Retrieve parameter type definitions from schema/config store using `type` field
|
3. **Type Definition Lookup**: Retrieve parameter type definitions from schema/config store using `type` field
|
||||||
4. **UI Form Generation**: Use `description` and `order` fields to create ordered parameter forms
|
4. **UI Form Generation**:
|
||||||
5. **Validation**: Validate user-provided parameters against type definitions
|
- Use `description` and `order` fields to create ordered parameter forms
|
||||||
6. **Default Application**: Apply default values for missing parameters from type definitions
|
- Parameters with `advanced: true` are hidden in basic mode or grouped in an "Advanced" section
|
||||||
7. **Template Substitution**: Replace parameter placeholders in processor parameters with validated values
|
- Parameters with `controlled-by` may be hidden in simple mode if they inherit from their controller
|
||||||
8. **Processor Instantiation**: Create processors with substituted parameters
|
5. **Parameter Inheritance Resolution**:
|
||||||
|
- For parameters with `controlled-by` field, check if a value was explicitly provided
|
||||||
|
- If no explicit value provided, inherit the value from the controlling parameter
|
||||||
|
- If the controlling parameter also has no value, use the default from the type definition
|
||||||
|
6. **Validation**: Validate user-provided and inherited parameters against type definitions
|
||||||
|
7. **Default Application**: Apply default values for missing parameters from type definitions
|
||||||
|
8. **Template Substitution**: Replace parameter placeholders in processor parameters with resolved values
|
||||||
|
9. **Processor Instantiation**: Create processors with substituted parameters
|
||||||
|
|
||||||
|
#### Parameter Inheritance with controlled-by
|
||||||
|
|
||||||
|
The `controlled-by` field enables parameter value inheritance, particularly useful for simplifying user interfaces while maintaining flexibility:
|
||||||
|
|
||||||
|
**Example Scenario**:
|
||||||
|
- `llm-model` parameter controls the primary LLM model
|
||||||
|
- `llm-rag-model` parameter has `"controlled-by": "llm-model"`
|
||||||
|
- In simple mode, setting `llm-model` to "gpt-4" automatically sets `llm-rag-model` to "gpt-4" as well
|
||||||
|
- In advanced mode, users can override `llm-rag-model` with a different value
|
||||||
|
|
||||||
|
**Resolution Rules**:
|
||||||
|
1. If a parameter has an explicitly provided value, use that value
|
||||||
|
2. If no explicit value and `controlled-by` is set, use the controlling parameter's value
|
||||||
|
3. If the controlling parameter has no value, fall back to the default from the type definition
|
||||||
|
4. Circular dependencies in `controlled-by` relationships result in a validation error
|
||||||
|
|
||||||
|
**UI Behavior**:
|
||||||
|
- In basic/simple mode: Parameters with `controlled-by` may be hidden or shown as read-only with inherited value
|
||||||
|
- In advanced mode: All parameters are shown and can be individually configured
|
||||||
|
- When a controlling parameter changes, dependent parameters update automatically unless explicitly overridden
|
||||||
|
|
||||||
#### Pulsar Integration
|
#### Pulsar Integration
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ tg-show-kg-cores = "trustgraph.cli.show_kg_cores:main"
|
||||||
tg-show-library-documents = "trustgraph.cli.show_library_documents:main"
|
tg-show-library-documents = "trustgraph.cli.show_library_documents:main"
|
||||||
tg-show-library-processing = "trustgraph.cli.show_library_processing:main"
|
tg-show-library-processing = "trustgraph.cli.show_library_processing:main"
|
||||||
tg-show-mcp-tools = "trustgraph.cli.show_mcp_tools:main"
|
tg-show-mcp-tools = "trustgraph.cli.show_mcp_tools:main"
|
||||||
|
tg-show-parameter-types = "trustgraph.cli.show_parameter_types:main"
|
||||||
tg-show-processor-state = "trustgraph.cli.show_processor_state:main"
|
tg-show-processor-state = "trustgraph.cli.show_processor_state:main"
|
||||||
tg-show-prompts = "trustgraph.cli.show_prompts:main"
|
tg-show-prompts = "trustgraph.cli.show_prompts:main"
|
||||||
tg-show-token-costs = "trustgraph.cli.show_token_costs:main"
|
tg-show-token-costs = "trustgraph.cli.show_token_costs:main"
|
||||||
|
|
|
||||||
|
|
@ -5,38 +5,93 @@ Shows all defined flow classes.
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import tabulate
|
import tabulate
|
||||||
from trustgraph.api import Api
|
from trustgraph.api import Api, ConfigKey
|
||||||
import json
|
import json
|
||||||
|
|
||||||
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
|
default_url = os.getenv("TRUSTGRAPH_URL", 'http://localhost:8088/')
|
||||||
|
|
||||||
|
def format_parameters(params_metadata, config_api):
|
||||||
|
"""
|
||||||
|
Format parameter metadata for display
|
||||||
|
|
||||||
|
Args:
|
||||||
|
params_metadata: Parameter definitions from flow class
|
||||||
|
config_api: API client to get parameter type information
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Formatted string describing parameters
|
||||||
|
"""
|
||||||
|
if not params_metadata:
|
||||||
|
return "None"
|
||||||
|
|
||||||
|
param_list = []
|
||||||
|
|
||||||
|
# Sort parameters by order if available
|
||||||
|
sorted_params = sorted(
|
||||||
|
params_metadata.items(),
|
||||||
|
key=lambda x: x[1].get("order", 999)
|
||||||
|
)
|
||||||
|
|
||||||
|
for param_name, param_meta in sorted_params:
|
||||||
|
description = param_meta.get("description", param_name)
|
||||||
|
param_type = param_meta.get("type", "unknown")
|
||||||
|
|
||||||
|
# Get type information if available
|
||||||
|
type_info = param_type
|
||||||
|
if config_api:
|
||||||
|
try:
|
||||||
|
key = ConfigKey("parameter-types", param_type)
|
||||||
|
type_def_value = config_api.get([key])[0].value
|
||||||
|
param_type_def = json.loads(type_def_value)
|
||||||
|
|
||||||
|
# Add default value if available
|
||||||
|
default = param_type_def.get("default")
|
||||||
|
if default is not None:
|
||||||
|
type_info = f"{param_type} (default: {default})"
|
||||||
|
|
||||||
|
except:
|
||||||
|
# If we can't get type definition, just show the type name
|
||||||
|
pass
|
||||||
|
|
||||||
|
param_list.append(f" {param_name}: {description} [{type_info}]")
|
||||||
|
|
||||||
|
return "\n".join(param_list)
|
||||||
|
|
||||||
def show_flow_classes(url):
|
def show_flow_classes(url):
|
||||||
|
|
||||||
api = Api(url).flow()
|
api = Api(url)
|
||||||
|
flow_api = api.flow()
|
||||||
|
config_api = api.config()
|
||||||
|
|
||||||
class_names = api.list_classes()
|
class_names = flow_api.list_classes()
|
||||||
|
|
||||||
if len(class_names) == 0:
|
if len(class_names) == 0:
|
||||||
print("No flows.")
|
print("No flow classes.")
|
||||||
return
|
return
|
||||||
|
|
||||||
classes = []
|
|
||||||
|
|
||||||
for class_name in class_names:
|
for class_name in class_names:
|
||||||
cls = api.get_class(class_name)
|
cls = flow_api.get_class(class_name)
|
||||||
classes.append((
|
|
||||||
class_name,
|
|
||||||
cls.get("description", ""),
|
|
||||||
", ".join(cls.get("tags", [])),
|
|
||||||
))
|
|
||||||
|
|
||||||
print(tabulate.tabulate(
|
table = []
|
||||||
classes,
|
table.append(("name", class_name))
|
||||||
tablefmt="pretty",
|
table.append(("description", cls.get("description", "")))
|
||||||
maxcolwidths=[None, 40, 20],
|
|
||||||
stralign="left",
|
tags = cls.get("tags", [])
|
||||||
headers = ["flow class", "description", "tags"],
|
if tags:
|
||||||
))
|
table.append(("tags", ", ".join(tags)))
|
||||||
|
|
||||||
|
# Show parameters if they exist
|
||||||
|
parameters = cls.get("parameters", {})
|
||||||
|
if parameters:
|
||||||
|
param_str = format_parameters(parameters, config_api)
|
||||||
|
table.append(("parameters", param_str))
|
||||||
|
|
||||||
|
print(tabulate.tabulate(
|
||||||
|
table,
|
||||||
|
tablefmt="pretty",
|
||||||
|
stralign="left",
|
||||||
|
))
|
||||||
|
print()
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,89 @@ def describe_interfaces(intdefs, flow):
|
||||||
|
|
||||||
return "\n".join(lst)
|
return "\n".join(lst)
|
||||||
|
|
||||||
|
def get_enum_description(param_value, param_type_def):
|
||||||
|
"""
|
||||||
|
Get the human-readable description for an enum value
|
||||||
|
|
||||||
|
Args:
|
||||||
|
param_value: The actual parameter value (e.g., "gpt-4")
|
||||||
|
param_type_def: The parameter type definition containing enum objects
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Human-readable description or the original value if not found
|
||||||
|
"""
|
||||||
|
enum_list = param_type_def.get("enum", [])
|
||||||
|
|
||||||
|
# Handle both old format (strings) and new format (objects with id/description)
|
||||||
|
for enum_item in enum_list:
|
||||||
|
if isinstance(enum_item, dict):
|
||||||
|
if enum_item.get("id") == param_value:
|
||||||
|
return enum_item.get("description", param_value)
|
||||||
|
elif enum_item == param_value:
|
||||||
|
return param_value
|
||||||
|
|
||||||
|
# If not found in enum, return original value
|
||||||
|
return param_value
|
||||||
|
|
||||||
|
def format_parameters(flow_params, class_params_metadata, config_api):
|
||||||
|
"""
|
||||||
|
Format flow parameters with their human-readable descriptions
|
||||||
|
|
||||||
|
Args:
|
||||||
|
flow_params: The actual parameter values used in the flow
|
||||||
|
class_params_metadata: The parameter metadata from the flow class definition
|
||||||
|
config_api: API client to retrieve parameter type definitions
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Formatted string of parameters with descriptions
|
||||||
|
"""
|
||||||
|
if not flow_params:
|
||||||
|
return "None"
|
||||||
|
|
||||||
|
param_list = []
|
||||||
|
|
||||||
|
# Sort parameters by order if available
|
||||||
|
sorted_params = sorted(
|
||||||
|
class_params_metadata.items(),
|
||||||
|
key=lambda x: x[1].get("order", 999)
|
||||||
|
)
|
||||||
|
|
||||||
|
for param_name, param_meta in sorted_params:
|
||||||
|
if param_name in flow_params:
|
||||||
|
value = flow_params[param_name]
|
||||||
|
description = param_meta.get("description", param_name)
|
||||||
|
param_type = param_meta.get("type", "")
|
||||||
|
controlled_by = param_meta.get("controlled-by", None)
|
||||||
|
|
||||||
|
# Try to get enum description if this parameter has a type definition
|
||||||
|
display_value = value
|
||||||
|
if param_type and config_api:
|
||||||
|
try:
|
||||||
|
from trustgraph.api import ConfigKey
|
||||||
|
key = ConfigKey("parameter-types", param_type)
|
||||||
|
type_def_value = config_api.get([key])[0].value
|
||||||
|
param_type_def = json.loads(type_def_value)
|
||||||
|
display_value = get_enum_description(value, param_type_def)
|
||||||
|
except:
|
||||||
|
# If we can't get the type definition, just use the original value
|
||||||
|
display_value = value
|
||||||
|
|
||||||
|
# Format the parameter line
|
||||||
|
line = f"• {description}: {display_value}"
|
||||||
|
|
||||||
|
# Add controlled-by indicator if present
|
||||||
|
if controlled_by:
|
||||||
|
line += f" (controlled by {controlled_by})"
|
||||||
|
|
||||||
|
param_list.append(line)
|
||||||
|
|
||||||
|
# Add any parameters that aren't in the class metadata (shouldn't happen normally)
|
||||||
|
for param_name, value in flow_params.items():
|
||||||
|
if param_name not in class_params_metadata:
|
||||||
|
param_list.append(f"• {param_name}: {value} (undefined)")
|
||||||
|
|
||||||
|
return "\n".join(param_list) if param_list else "None"
|
||||||
|
|
||||||
def show_flows(url):
|
def show_flows(url):
|
||||||
|
|
||||||
api = Api(url)
|
api = Api(url)
|
||||||
|
|
@ -75,10 +158,23 @@ def show_flows(url):
|
||||||
table.append(("class", flow.get("class-name", "")))
|
table.append(("class", flow.get("class-name", "")))
|
||||||
table.append(("desc", flow.get("description", "")))
|
table.append(("desc", flow.get("description", "")))
|
||||||
|
|
||||||
# Display parameters if they exist
|
# Display parameters with human-readable descriptions
|
||||||
parameters = flow.get("parameters", {})
|
parameters = flow.get("parameters", {})
|
||||||
if parameters:
|
if parameters:
|
||||||
param_str = json.dumps(parameters, indent=2)
|
# Try to get the flow class definition for parameter metadata
|
||||||
|
class_name = flow.get("class-name", "")
|
||||||
|
if class_name:
|
||||||
|
try:
|
||||||
|
flow_class = flow_api.get_class(class_name)
|
||||||
|
class_params_metadata = flow_class.get("parameters", {})
|
||||||
|
param_str = format_parameters(parameters, class_params_metadata, config_api)
|
||||||
|
except Exception as e:
|
||||||
|
# Fallback to JSON if we can't get the class definition
|
||||||
|
param_str = json.dumps(parameters, indent=2)
|
||||||
|
else:
|
||||||
|
# No class name, fallback to JSON
|
||||||
|
param_str = json.dumps(parameters, indent=2)
|
||||||
|
|
||||||
table.append(("parameters", param_str))
|
table.append(("parameters", param_str))
|
||||||
|
|
||||||
table.append(("queue", describe_interfaces(interface_defs, flow)))
|
table.append(("queue", describe_interfaces(interface_defs, flow)))
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
"""
|
"""
|
||||||
Starts a processing flow using a defined flow class
|
Starts a processing flow using a defined flow class.
|
||||||
|
|
||||||
|
Parameters can be provided in three ways:
|
||||||
|
1. As key=value pairs: --param model=gpt-4 --param temp=0.7
|
||||||
|
2. As JSON string: -p '{"model": "gpt-4", "temp": 0.7}'
|
||||||
|
3. As JSON file: --parameters-file params.json
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
@ -62,6 +67,12 @@ def main():
|
||||||
help='Path to JSON file containing flow parameters',
|
help='Path to JSON file containing flow parameters',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--param',
|
||||||
|
action='append',
|
||||||
|
help='Flow parameter as key=value pair (can be used multiple times, e.g., --param model=gpt-4 --param temp=0.7)',
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -73,6 +84,34 @@ def main():
|
||||||
parameters = json.load(f)
|
parameters = json.load(f)
|
||||||
elif args.parameters:
|
elif args.parameters:
|
||||||
parameters = json.loads(args.parameters)
|
parameters = json.loads(args.parameters)
|
||||||
|
elif args.param:
|
||||||
|
# Parse key=value pairs
|
||||||
|
parameters = {}
|
||||||
|
for param in args.param:
|
||||||
|
if '=' not in param:
|
||||||
|
raise ValueError(f"Invalid parameter format: {param}. Expected key=value")
|
||||||
|
|
||||||
|
key, value = param.split('=', 1)
|
||||||
|
key = key.strip()
|
||||||
|
value = value.strip()
|
||||||
|
|
||||||
|
# Try to parse value as JSON first (for numbers, booleans, etc.)
|
||||||
|
try:
|
||||||
|
# Handle common cases where we want to preserve the string
|
||||||
|
if value.lower() in ['true', 'false']:
|
||||||
|
parameters[key] = value.lower() == 'true'
|
||||||
|
elif value.replace('.', '').replace('-', '').isdigit():
|
||||||
|
# Check if it's a number
|
||||||
|
if '.' in value:
|
||||||
|
parameters[key] = float(value)
|
||||||
|
else:
|
||||||
|
parameters[key] = int(value)
|
||||||
|
else:
|
||||||
|
# Keep as string
|
||||||
|
parameters[key] = value
|
||||||
|
except ValueError:
|
||||||
|
# If JSON parsing fails, treat as string
|
||||||
|
parameters[key] = value
|
||||||
|
|
||||||
start_flow(
|
start_flow(
|
||||||
url = args.api_url,
|
url = args.api_url,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue