Skip to content
OpenCMLPublic

About

Camel is a graph-native, multi-stage, and type-driven domain-specific language (DSL) designed to bridge the gap between AI research and production deployment.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

21 stars

Watchers

2 watching

Forks

Latest commit

 

History

7,415 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Camel

The program is the graph.

Camel is a graph-native general-purpose programming language, with AI as its primary application.

CI Version License: MIT Platforms VS Code Stars

Why Camel · Zen · A taste · Quick start · Tutorial · Documentation · Roadmap · 中文


Why Camel

Most languages write a program as instructions for a machine to carry out one step at a time. Yet what compilers, parallel runtimes, automatic differentiation and GPU back ends actually need is a graph: what is to be computed, and what depends on what. So the graph has to be recovered from the code after the fact, by tracing, capturing and analysis. The recovered graph breaks apart, loses what the side effects meant, and the transformations applied to it become a black box the user cannot touch.

In Camel the program is the graph. What you write is the intent of the computation and its dependencies; order is written only where you need it. From that:

  • The compiler gets exactly what you wrote: nothing is traced, the graph does not break, and computations that do not depend on each other are free to run in parallel.
  • Transformations are ordinary functions: optimizing, differentiating, moving to a GPU and exporting are passes over the graph. You can look at them, swap them, and write your own in Camel.
  • Knowledge about optimization is code you can check: an algebraic law is a rule, and check tells you whether it holds.
  • One program, many ways to run it: interpreted, JIT-compiled, on a GPU, or exported to ONNX or C++, with the same meaning.

These properties hold for every program where computation matters more than control flow. Training and deploying models is the most pressing of them, which is why AI is Camel's primary application, though not its only one. More in Why Camel.

The Zen of Camel

  1. Let the graph speak. All computation is a graph of intent.
  2. Graphs are primitives, not artifacts. Graphs are the native shape of intent, not a byproduct of code.
  3. Every construct is a piece of the graph. If a construct has no clear place on the graph, it does not belong in the language.
  4. Async by nature, sync when explicit. Order emerges from dependencies, not from syntax.
  5. Execution is polymorphic and multi-staged. Passes are functions, functions are graphs: compiling, optimizing and running are all stages of rewriting.
  6. Keep code pure, let runtimes specialize. Context is injected at runtime, not embedded in code.
  7. One language, all the way down. Types, rules and passes are all written in Camel itself.
  8. Let compilers bear the burden. Scheduling, mapping, fusing, and lowering — these are not your job.

camel --zen prints them.

Highlights

🧭 Graph-native Every construct maps to a fixed piece of the graph. Evaluation follows dependencies; independent work runs in parallel without being asked.
🔁 Passes are functions Optimization, differentiation, export and execution are graph-to-graph passes you compose on the command line, or write yourself in Camel.
📐 Rules you can verify Write an algebraic law once, generic over types; the rewrite engine applies it, and check proves, refutes or samples it.
∂ Differentiable by construction grad(f) rewrites the graph of f into the graph of its derivative, at compile time, so every later pass optimizes it too.
🧮 Arrays with shapes f32[n, k] is one type for every rank; dimension names are checked across a call, and memory is updated in place whenever nothing else can see it.
🚀 Many back ends A node VM, a bytecode VM, a JIT, a parallel scheduler, GPU kernels, ONNX and standalone C++ — one meaning everywhere.
🐍 Plays well with Python Call Camel modules from Python with zero-copy arrays, and get Camel's diagnostics as Python exceptions with locations.
🛠️ Real tooling A language server, a formatter, a debugger that steps through passes, and diagnostics that come with machine-applicable fixes.

A taste

Fit a line by gradient descent. grad(loss) is not a library call evaluated step by step: it is a graph rewrite, and the derivative it builds is an ordinary graph the optimizer and the JIT see.

import { grad } from autodiff

with <w: float>
func loss(x: float, y: float): float {
    let e = w * x - y
    return e * e
}

func main(): int sync {
    let fitted = loop w = 0.0 for i in 0..100 do w - 0.01 * grad(loss)<w>(3.0, 6.0)
    println(fitted)                  // close to 2.0
    return 0
}

The words after the file name are the passes to run, in order:

camel fit.cml                        # run on the node VM
camel fit.cml std::gir               # print the graph (Graphviz DOT) instead of running
camel fit.cml std::macro std::opt std::jit   # expand grad, optimize, run with the JIT
camel fit.cml std::opt::saturate std::gir    # keep every equivalent form and draw them side by side

Optimizations are written in Camel too. A law is stated once, for every type that satisfies its condition:

rule add_zero::<T>(x: T) when is_integer::<T>() { x + 0 => x }

The language and the graph

In the source On the graph What follows
An expression, an operator call Nodes and data edges Evaluation follows dependencies; independent nodes may run in any order or in parallel
A function A subgraph; a call is a node A function's behaviour is decided by the function itself
A sync block Order between the effects it contains Effects run in the order written
if, match, a ?? b, a !! b A branch Errors and nulls are values, handled by branches
loop … do … A loop node with its state Iteration is an expression whose value is the last state
A generic function A subgraph template, instantiated per set of concrete types Only concrete types are on the graph
A pass A function from a graph to a graph An open pipeline

The rules behind this table are in the design principles.

Quick start

Install

pip install camel-lang

This puts the camel command on your PATH, and import camel in Python. Wheels are published for Linux (x64, arm64), macOS (Apple silicon) and Windows (x64). The camel command installs on any Python 3; calling Camel from Python needs the CPython version this release built its interop wheel for, and that wheel's file name says which it is (cp311, cp313, ...). There is one interop wheel per platform rather than one for every Python version, so install camel-lang with that interpreter.

On arm64 (Linux arm64 and Apple silicon) the wheel has no native code generator for std::jit: the pass is accepted and the program runs on the bytecode interpreter, as std::fvm does, with the same results, and the build says so once in its log (-v). See Command line.

Build from source

You need Clang 19+, CMake 3.25+, Ninja, Conan 2.10+ and Node.js 18+. docs/setup.en.md lists the toolchain per platform.

git clone https://github.com/OpenCML/Camel.git && cd Camel
npm install          # npm packages and the C++ dependencies (needs network access)
npm run build        # Release build into out/latest

Put out/latest/bin on your PATH and set CAMEL_HOME to out/latest. CI builds and tests Linux (x64, arm64), macOS (Apple silicon) and Windows (x64).

Hello, Camel

func main(): int sync {
    println('Hello, Camel!')
    return 0
}
camel hello.cml
Hello, Camel!

Editor support

Install OpenCML-Ext for VS Code: highlighting, language services, an interactive graph browser, and a debugger that can pause between passes. Point opencmlLanguageServer.camelPath at your camel executable. See the extension README and the debugging guide.

From Python

import camel

stats = camel.load("stats.cml")      # a Camel module
y = stats.normalize(x)               # NumPy arrays cross without a copy

A failure arrives as a camel.CamelError carrying the diagnostic and its location.

Documentation

📘 Tutorial From the first program to rules, passes, gradients and export
💡 Why Camel What problem Camel solves and why the program should be the graph
📖 Language reference Every construct, precisely
📚 Standard library Every module and function
🧪 Examples Short task-oriented programs: files, JSON, a CLI tool, parallel map, a training step
⌨️ Command line · Diagnostics Options, passes, and camel --explain <name>
🤖 Camel for AI · llms.txt What a model needs to write Camel
🧱 Design principles The rules the language is built on (中文, authoritative)
⚙️ Technical docs The pipeline, the graph IR, the runtime

Status

Camel is under active development and has not reached 1.0. The language changes without compatibility shims: when a spelling is replaced, the old one is simply gone. Release notes are in changes.log, and the plan is in the roadmap.

Contributing

Issues and pull requests are welcome. Start with the contributing guide, and please follow the code of conduct. Security issues go through the security policy.

License

Camel is released under the MIT License.

About

Camel is a graph-native, multi-stage, and type-driven domain-specific language (DSL) designed to bridge the gap between AI research and production deployment.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

21 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages