Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 92 additions & 122 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,160 +1,130 @@
# Template Engine
# LLM-Based Generic Executor for TemplateArchiveProcessor

This is the [Accord Project](https://accordproject.org) template engine. Rich-text templates are defined in TemplateMark (either as markdown files, or JSON documents) and are then merged with JSON data to produce output documents. Templates may contain [TypeScript](https://www.typescriptlang.org) expressions.
## Overview

## Resources
This contribution extends the `TemplateArchiveProcessor` to support a **generic LLM-based contract logic executor**.

- [Getting Started Video](https://vimeo.com/manage/videos/845273411)
- [Template Playground](https://playground.accordproject.org)
- [Running Code](https://replit.com/@dselman/AccordProjectTemplateEngine-Hello-World)
The goal is to enable execution of Accord Project templates **without requiring explicit TypeScript `logic.ts` files**, by delegating reasoning to a Large Language Model (LLM).

The core template engine is a JSON to JSON transformation that converts TemplateMark JSON + agreement data (JSON) to AgreementMark JSON.
This implementation introduces:

> Note: Use the `@accordproject/markdown-transform` project to convert markdown templates to TemplateMark JSON and to convert AgreementMark JSON to output formats (HTML, PDF, DOCX etc.). For command-line usage please use `@accordproject/template-cli`.
- A fallback and force execution mode using an LLM
- A Groq-based reasoning backend
- A runtime-compatible output normalization layer
- Minimal changes to existing execution flow to preserve backward compatibility

TemplateMark is a document object model that describes a rich-text template, with embedded variables, conditional sections, formulae etc. TemplateMark uses embedded TypeScript expressions for conditionals and calculations.
---

> The format of both TemplateMark and AgreementMark is specified using the [Concerto](https://concerto.accordproject.org) data modeling language.
## Key Features

At a high-level the template engine converts a TemplateMark DOM to an AgreementMark DOM, evaluating TypeScript expressions for conditional sections and formulae, and replaces variable references with variable values from the supplied agreement data.
### 1. LLM Execution Modes

![Template Interpreter](./assets/template-interpreter.png)
The processor now supports three execution modes:

## Hello World Template
| Mode | Behavior |
|------------|--------|
| `disabled` | Only TypeScript logic is used (default behavior) |
| `fallback` | Uses LLM only if no TypeScript logic is found |
| `force` | Always uses LLM, ignoring TypeScript logic |

Let's create the simplest template imaginable, the infamous "hello world"!
---

> The code for this test is available at: https://github.com/accordproject/template-engine/blob/main/test/HelloWorld.test.ts
### 2. Generic Contract Execution via LLM

### Template Data Model
The LLM executor:

First create a template data model in Concerto syntax. The data model defines the structure of the data to be merged with the template. In this case the template model contains a single property `message` of type `String`. The property is required (it is not `optional`).
- Takes as input:
- Contract text
- Concerto model definitions
- Template data
- Current state
- Incoming request
- Produces:
- `result` (response object)
- `state` (updated contract state)
- `events` (emitted events)

```javascript
namespace helloworld@1.0.0
This mimics the behavior of a typical `logic.ts` implementation.

@template
concept TemplateData {
o String message
}
```

### TemplateMark (extended markdown)

Next define the TemplateMark for the template. In this case it is the plain-text world `"Hello"` followed by a space, then the variable `message` followed by `"."`.

```markdown
Hello {{message}}.
```

> Note that in this case the template is defined using an extended markdown syntax (rich-text with embedded variables etc.). The `@accordproject/markdown-transform` packages are used to convert the markdown to TemplateMark JSON, for use by the template engine.

### Generate AgreementMark from Data (JSON)

Define an **instance** of the `helloworld@1.0.0.TemplateData` data model. In this case setting the value of the `message` property to the string "World".

```typescript
const data = {
$class: 'helloworld@1.0.0.TemplateData',
message: 'World',
};
```
### Output AgreementMark (JSON)

When the TemplateMark and the data JSON is passed to the Template Engine it merges the two, in this case by simply replacing the reference to the `message` variable with its value from the data JSON and to produce an AgreementMark JSON document.

This AgreementMark JSON document can then be passed to the `@accordproject/markdown-transform` modules for conversion to markdown, PDF, HTML.

```json
{
"$class": "org.accordproject.commonmark@0.5.0.Document",
"xmlns": "http://commonmark.org/xml/1.0",
"nodes": [
{
"$class": "org.accordproject.commonmark@0.5.0.Paragraph",
"nodes": [
{
"$class": "org.accordproject.commonmark@0.5.0.Paragraph",
"nodes": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "Hello "
},
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"value": "World",
"name": "message",
"elementType": "String"
},
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "."
}
]
}
]
}
]
}
```
---

## Next Steps
### 3. Runtime Output Normalization

The Hello World example just scratches the surface of what can be accomplished! TemplateMark can define optional sections, conditional sections, TypeScript formulae/calculations and even reference external data.
Since LLM outputs may omit runtime metadata, a normalization layer ensures compatibility with Accord runtime expectations.

Refer to the [full](https://github.com/accordproject/template-engine/tree/main/test/templates/full) example for details.
The executor automatically injects:

> More detailed syntax documentation is to come!
Read the existing documentation at: https://docs.accordproject.org/docs/markup-templatemark.html
- `$timestamp` into:
- `result`
- `events`
- `$identifier` into:
- `state`
Additionally, object field ordering is standardized to match existing engine output ie (result, events, state)

## Why create a new template engine?
---

There are many great Open Source template engines available, such as [Mustache](https://mustache.github.io), [Handlebars](https://handlebarsjs.com) or [EJS](https://ejs.co), so why create yet another?
### 4. Logging and Execution Visibility

### 1. Input and Output Format Agnostic
Execution paths are explicitly logged:

Most template engines are fundamentally **text based** — i.e. they treat templates as text strings and are glorified "find and replace" machines. This approach creates a coupling between the input format of the template, say, a DOCX file, and the output of the template engine, which in the case of a DOCX template, has to be a DOCX file. This makes supporting multiple input and output formats difficult.
- Execution mode (`force`, `fallback`, `disabled`)
- Selected executor:
- TypeScript logic
- LLM executor

The Accord Project template engine breaks the coupling between the template input format and the engine output format, and moves data format conversion outside of the core template engine. Templates at the engine level are TemplateMark JSON documents and the output from the template engine is an AgreementMark JSON document. Separate libraries are used to convert source templates into TemplateMark JSON, or to render AgreementMark JSON to an output format.
This allows users to verify behavior at runtime.

This flexibility allows a markdown template to be created that is used to create HTML, PDF or DOCX. One can even imagine using DOCX templates to create HTML or PDF files, or other scenarios.
---

### 2. TemplateMark as a Defined Format
## Architecture Changes

TemplateMark JSON is a well-defined file format, meaning that powerful template editors can be created to define it: including widgets and user-experience for defining conditional sections, and formulae, and offering template preview and integrated testing. Template editing is closer to programming in our opinion than word-processing.
### TemplateArchiveProcessor

We encourage community and commercial innovation in this area!
Modified to:

### 3. Full Logic Support
- Detect presence of TypeScript logic
- Route execution based on mode
- Delegate execution to:
- TypeScript evaluator (existing)
- LLM executor (new)

Unlike some templating systems which prohibit, or minimize, logic in templates, Accord Project templates fully embrace templates that may contain sophisticated logic: conditional logic to determine what text to include, or even calculations, for example to calculate the monthly payments for a mortgage based on the term of the mortgage, the amount and the interest rate.
Execution flow:

### 4. Type-safety

Given the ability for templates to contain logic there's an imperative to ensure that the templates are **safe** - i.e. when a template is merged with well-structured data it is guaranteed to produce well-structured output.

Too many templating engines fail in unpredictable ways at runtime, or silently generate invalid output, when presented with data — unacceptable for enterprise usage.

Accord Project templates are therefore **strongly-typed**. The logic in templates is expressed in [TypeScript](https://www.typescriptlang.org). TypeScript is a strongly-typed, general purpose programming language, supported by a vibrant Open Source and enterprise community. TypeScript compiles to JavaScript for easy execution on most platforms.

### 5. Data Model

The rich-text with variables of a template is associated with a [Concerto data model](https://concerto.accordproject.org). The Concerto data model defines the structure of the data required for the template, and is used to statically compile the template and verify type-safety, and is also used at runtime to ensure that incoming data is well structured.

### 6. Compilation
```ts
if (mode === 'force') → LLM
else if (has TS logic) → TS executor
else if (fallback enabled) → LLM
else → error
```

Templates may be statically compiled to TypeScript programs, enforcing type-safety, ensuring that no unsafe code evaluation ("eval") is required at runtime, and easing integration into applications.
### LLMExecutor
New component responsible for:
- Prompt construction
- Model invocation via Groq API
- JSON parsing and validation
- Output normalization

### GroqReasoner
Wrapper around Groq API used for:
- Chat completion
- Retry handling
- Configurable parameters (temperature, tokens, etc.)

## Installation and running the example
Inside the repository root:
```bash
npm install
npm run build
```

The template compiler is a separate project, hosted here: https://github.com/accordproject/template-compiler
A sample template is provided in `late_delivery` folder:

## Install
```bash
cd late_delivery/

Note that this module is primarily intended for tool authors, or developers embedding template engines within applications. For command-line usage please refer to the `@accordproject/template-cli` package which implements a full pipeline to convert markdown templates plus JSON data to supported output formats, such as HTML, DOCX or PDF.
# Set API Key
export GROQ_API_KEY="your_api_key_here"

# Run the Example
node run.js
```
npm install @accordproject/template-engine --save
```

## License <a name="license"></a>
Accord Project source code files are made available under the Apache License, Version 2.0 (Apache-2.0), located in the LICENSE file. Accord Project documentation files are made available under the Creative Commons Attribution 4.0 International License (CC-BY-4.0), available at http://creativecommons.org/licenses/by/4.0/.

7 changes: 7 additions & 0 deletions late_delivery/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

# Clause Template: Late Delivery And Penalty

## Sample

Late Delivery and Penalty. In case of delayed delivery except for Force Majeure cases, the Seller shall pay to the Buyer for every 2 days of delay penalty amounting to 10.5% of total value of the Equipment whose delivery has been delayed. Any fractional part of a day is to be considered a full day. The total amount of penalty shall not, however, exceed 55% of the total value of the Equipment involved in late delivery. If the delay is more than 15 days, the Buyer is entitled to terminate this Contract.

Loading