Core concepts
The main building blocks
Pipeline
A Pipeline is the graph that executes your complete inference workflow.
You either:
- load it from a
.denkflowfile, or - build it manually from
.denkmodelfiles and utility nodes
A pipeline can be modified only before initialization.
- Python
- C / C++
# Load from export
pipeline = Pipeline.from_denkflow("model.denkflow", pat="YOUR-PAT")
# Or build manually
pipeline = Pipeline()
pipeline.add_image_resize_node(...)
// Load from export
DenkflowPipeline* pipeline = NULL;
denkflow_pipeline_from_denkflow(&pipeline, "model.denkflow", (void*)license_source);
Node
A Node is one processing step inside the pipeline, such as:
- image resize
- object detection
- classification
- OCR
- segmentation
- anomaly detection
Topic
A Topic is the connection name used to move tensors between producers and consumers.
Topic strings follow this format:
[{node_name}]/{port_name}[?timeout={ms}]
- Node outputs and internal connections use
{node_name}/{port_name}— for exampleimage-resize/resized_imageorbb-filter/filtered_bounding_boxes. - Pipeline inputs and constants use an empty node name:
/port_name— for example/imagefor the external image input, or/target_sizefor a fixed resize dimension. - Optional timeout — append
?timeout=500to set a per-topic receive timeout in milliseconds.
Constant topic values
Instead of dedicated constant nodes, you set fixed tensor values on topics before initialize(). Constant topics must use the /port_name form (empty node name).
- Python
- C / C++
pipeline.set_constant_value("/target_size", np.array([1088, 1280], dtype=np.int64))
defaults = pipeline.get_constant_values() # before initialize()
pipeline.remove_constant_value("/target_size")
DenkflowConstantValueArray* constants = NULL;
DenkflowBaseTensor* tensor = NULL;
int64_t values[2] = {1088, 1280};
size_t shape[1] = {2};
denkflow_base_tensor_from_buffer(&tensor, values, DenkflowArrayDataType_Int64, shape, 1);
denkflow_pipeline_set_constant_value(pipeline, "/target_size", (void **)&tensor);
denkflow_pipeline_get_constant_values(&constants, pipeline);
denkflow_pipeline_remove_constant_value(pipeline, "/target_size");
denkflow_constant_value_array_free(&constants);
Build numeric tensors with denkflow_base_tensor_from_buffer before calling denkflow_pipeline_set_constant_value. Both functions consume the tensor pointer on success.
Each DenkflowConstantValue contains topic_name, tensor_type, shape/shape_length, data, and data_type (DenkflowArrayDataType enum).
Runtime parameters on exported pipelines
When you load a .denkflow file, graph constants from the export are applied automatically (for example /iou_threshold or /image_size). To supply different values on each run:
- Discover constant topics and their default values with
get_constant_values()beforeinitialize() - Call
remove_constant_value(topic)for each parameter you intend to override - Publish your own values before every
run()
See Runtime parameters on exported pipelines for a full walkthrough.
Inspecting topics with TopicDescription
After initialize(), call get_topics() to list every topic in the pipeline. Each entry is a TopicDescription with:
topic_name— the topic stringtopic_type—ExternalInput,ExternalOutput, orInternalConnectiontensor_type— e.g.ImageTensor,BoundingBoxTensoris_constant—truewhen the topic has a fixed initializer value
- Python
- C / C++
pipeline.initialize()
for topic in pipeline.get_topics():
if topic.topic_type.name == "ExternalInput" and not topic.is_constant:
print("Publish to:", topic.topic_name)
if topic.topic_type.name == "ExternalOutput":
print("Subscribe to:", topic.topic_name)
DenkflowTopicDescriptionArray* topics = NULL;
denkflow_initialized_pipeline_get_topics(&topics, initialized_pipeline);
for (size_t i = 0; i < topics->topic_information_length; ++i) {
DenkflowTopicDescription* t = &topics->topic_information[i];
// t->topic_name, t->topic_type, t->tensor_type, t->is_constant
}
Tensor
A Tensor is a payload flowing through the graph.
Common tensor types include:
ImageTensorBoundingBoxTensorScalarTensorOcrTensorSegmentationMaskTensorInstanceSegmentationMaskTensor
Receiver
A Receiver subscribes to a topic and lets you wait for output data.
This is how you collect inference results after calling run().
- Python
- C / C++
receiver = pipeline.subscribe("filter/output")
# Then use the typed receive method that matches the topic's tensor type:
# receiver.receive_bounding_box_tensor()
DenkflowReceiverTensor* receiver = NULL;
denkflow_initialized_pipeline_subscribe(&receiver, initialized_pipeline, "filter/output");
Typical evaluation workflow
Most inference scripts follow this shape:
- Create or load a pipeline
- Initialize the pipeline
- Subscribe to one or more output topics
- Publish input tensors
- Call
run() - Receive and decode the result
- Python
- C / C++
pipeline = Pipeline.from_denkflow("model.denkflow", pat="PAT")
pipeline.initialize()
# Discover topics (see Topic section above)
input_topics = [
t.topic_name for t in pipeline.get_topics()
if t.topic_type.name == "ExternalInput" and not t.is_constant
]
output_topics = [
t.topic_name for t in pipeline.get_topics()
if t.topic_type.name == "ExternalOutput"
]
receiver = pipeline.subscribe(output_topics[0])
pipeline.publish_image_tensor("/image", ImageTensor.from_file("image.jpg"))
pipeline.run()
objects = receiver.receive_bounding_box_tensor().to_objects(0.5)
denkflow_pipeline_from_denkflow(&pipeline, "model.denkflow", (void*)license_source);
denkflow_initialize_pipeline(&initialized_pipeline, &pipeline);
denkflow_initialized_pipeline_subscribe(&receiver, initialized_pipeline, "output/topic");
denkflow_image_tensor_from_file(&image_tensor, "image.jpg");
denkflow_initialized_pipeline_publish_tensor(initialized_pipeline, "/image", (void **)&image_tensor);
denkflow_initialized_pipeline_run(initialized_pipeline, 8000);
denkflow_receiver_receive_bounding_box_tensor(&tensor, receiver);
denkflow_bounding_box_tensor_to_objects(&results, tensor, 0.5f);
.denkflow versus .denkmodel
.denkflow
Use .denkflow when:
- you want the simplest deployment path
- you want export-target-specific runtime configuration
- you want quantized deployment artifacts
.denkmodel
Use .denkmodel when:
- you want to assemble the graph yourself
- you want to choose or force runtime strings like
cuda,tensorrt,directml, oropenvinofrom Python or C/C++ - you want to combine multiple models in one hand-built pipeline
Execution providers and device IDs
Each inference node runs on an execution provider (cpu, cuda, tensorrt, directml, or openvino). Custom pipelines select it via execution_provider= (Python) or the C-API equivalent; exported .denkflow files carry the runtime intent chosen at export time and can be redirected per node before initialization.
For the full provider list, device-id semantics (e.g. OpenVINO -1/-2/>=0), and override rules, see Runtime and Device Selection.
Recommended production strategy
- Export a
.denkflowfile from the Vision AI Hub - Install the SDK for the target runtime and language
- Keep the SDK data directory persistent (default paths are in Configuration; in Docker, mount a host volume at that default path or at the path
DENKFLOW_DATA_DIRECTORYpoints to) - Deploy and benchmark on the actual target hardware