ModelWorks logoModelWorks

Introduction

Introduction to ModelWorks

Introduction to ModelWorks

ModelWorks is an AI orchestration platform that allows developers to encapsulate logic in reusable, logical units called Circuits. Circuits enable you to stitch together API calls, data transformations, and custom code into a cohesive workflow that can be run on-demand, triggered by events, or scheduled to run at regular intervals.

This tutorial guides you through key concepts in ModelWorks. We start with the same "Hello World" circuit from the Quickstart Guide and gradually introduce new concepts, including:

  • Circuits and Namespaces: Organize your logic into isolated units.
  • Inputs and Parameters: Pass data into your circuit for flexible behavior.
  • Steps and Tasks: Define individual operations within a circuit.
  • Adapters: Connect to external services or protocols (e.g., HTTP, SSE).
  • Triggers: Schedule circuits using cron-like syntax or respond to events.

Key Use Cases

ModelWorks can power a wide range of automation and integration scenarios:

  • Workflows on Demand: Manually invoke a circuit or invoke it via an API call.
  • Event-Driven Automation: Trigger circuits when data arrives in a queue, webhook, or message bus.
  • Scheduled Jobs: Run pipelines daily, hourly, or at custom cron intervals.
  • Polyglot Scripting: Orchestrate scripts in Python, R, Julia, Node.js, or any other language.
  • Microservice Coordination: Call and combine multiple microservices into a single logical flow.
  • Batch Processing: Kick off ETL jobs, data ingestion syncs, dbt or Spark transformations.
  • Database Operations: Execute SQL queries and manage transactional workflows.
  • AI & ML Pipelines: Integrate model inference, data preprocessing, and results storage.
  • Chat & Business Logic: Serve as the infrastructure for chat clients, fine‑tuned prompts, and business rules via custom adapters.

Example Circuit: OpenAI Chat Completion

Below is a sample circuit that calls the OpenAI Chat Completion API (gpt-4o-mini) via a fetch step, streams the response using an SSE adapter, and outputs the accumulated chat content.

{
  "name": "OpenAI (gpt-4o-mini)",
  "description": "OpenAI Chat Completion Service powered by (gpt-4o-mini)",
  "document_type": "circuit",
  "engine_version": "1.0",
  "cost": 15,
  "env": {
    "api_key": "${{ secrets.api_key }}"
  },
  "inputs": [
    {
      "name": "messages",
      "description": "A list of messages comprising the conversation so far.",
      "value": "${{ input.messages }}",
      "type": "array",
      "required": true
    },
    {
      "name": "store",
      "description": "Whether or not to store the output for use in model training.",
      "value": "${{ input.store }}",
      "default_value": false,
      "type": "boolean",
      "required": false
    },
    {
      "name": "frequency_penalty",
      "description": "Penalize new tokens based on their existing frequency in the text.",
      "value": "${{ input.frequency_penalty }}",
      "default_value": 0,
      "type": "number",
      "required": false
    },
    {
      "name": "presence_penalty",
      "description": "Penalize new tokens if they appear in the text so far.",
      "value": "${{ input.presence_penalty }}",
      "default_value": 0,
      "type": "number",
      "required": false
    },
    {
      "name": "logit_bias",
      "description": "Modify the likelihood of specified tokens appearing in the completion.",
      "value": "${{ input.logit_bias }}",
      "default_value": null,
      "type": "object",
      "required": false
    },
    {
      "name": "temperature",
      "description": "Sampling temperature to use, between 0 and 2.",
      "value": "${{ input.temperature }}",
      "default_value": 1,
      "type": "number",
      "required": false
    },
    {
      "name": "top_p",
      "description": "Alternative to temperature, nucleus sampling with top_p probability mass.",
      "value": "${{ input.top_p }}",
      "default_value": 1,
      "type": "number",
      "required": false
    },
    {
      "name": "user",
      "description": "A unique identifier representing the end user for monitoring abuse.",
      "value": "${{ input.user }}",
      "default_value": null,
      "type": "string",
      "required": false
    }
  ],
  "steps": [
    {
      "name": "chat_completion_response",
      "description": "Generate a chat completion based on the conversation (gpt-4o-mini).",
      "function": "circuit.core.fetch",
      "input": {
        "url": "https://api.openai.com/v1/chat/completions",
        "method": "POST",
        "headers": {
          "Content-Type": "application/json",
          "Authorization": "Bearer ${{ env.api_key }}"
        },
        "body": {
          "model": "gpt-4o-mini",
          "messages": "${{ messages }}",
          "store": "${{ store }}",
          "frequency_penalty": "${{ frequency_penalty }}",
          "presence_penalty": "${{ presence_penalty }}",
          "logit_bias": "${{ logit_bias }}",
          "temperature": "${{ temperature }}",
          "top_p": "${{ top_p }}",
          "user": "${{ user }}",
          "stream": true
        }
      },
      "stream_mapping": [
        {
          "sse_selector": "choices[0].delta.content",
          "sse_name": "delta_accumulator"
        }
      ]
    }
  ],
  "adapters": [
    {
      "type": "OPEN_AI_SSE",
      "mapping": {
        "input": [
          { "from_adapter_variable_name": "messages", "to_circuit_variable_name": "messages" },
          { "from_adapter_variable_name": "model", "to_circuit_variable_name": "model" }
        ],
        "output": [
          { "from_circuit_variable_name": "chat_completion_output", "to_adapter_variable_name": "content" }
        ]
      }
    },
    {
      "type": "MODELWORKS_SSE"
    }
  ],
  "outputs": [
    {
      "name": "chat_completion_output",
      "description": "The response from OpenAI with the generated chat message.",
      "value": "${{ chat_completion_response.output.stream_accumulators.delta_accumulator }}"
    }
  ]
}

Feel free to modify this example as you follow along. In later sections, we’ll cover:

  1. Namespaces for multi-tenant isolation.
  2. Triggers to schedule circuits via cron or event hooks.
  3. Custom Adapters to integrate proprietary systems.

Let’s dive in with our first Hello World circuit!👩‍💻🚀