dcdmaker

package module
v0.2.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: MIT Imports: 17 Imported by: 0

README

dcdmaker

AI-powered DCD template generator. Parses source documents (DOCX) and generates reusable .dcd templates using Gemini, OpenAI, or any OpenAI-compatible API.

Installation

go get github.com/rachmanzz/dcdmaker

Library Usage

package main

import "github.com/rachmanzz/dcdmaker"

func main() {
    maker := dcdmaker.NewMaker(
        dcdmaker.Gemini(
            dcdmaker.WithModel("gemini-2.5-flash"),
            dcdmaker.WithTemperature(0.3),
        ),
        dcdmaker.Gemini(
            dcdmaker.WithModel("gemini-2.5-pro-exp-03-25"),
        ),
        dcdmaker.OpenAI(
            dcdmaker.WithOpenAIModel("gpt-4o"),
        ),
    )

    maker.
        Source("invoice.docx").
        OptionalPrompt("Create invoice template with number, date, customer, items, total").
        Run("templates/invoice.dcd")

    // Or get raw string (no file write)
    dcd, err := maker.Generate()
}
PredictableKeys

Control variable names and structure — AI forced to use exact keys:

maker.
    Source("invoice.docx").
    PredictableKeys(
        dcdmaker.Object("info", "invoice_no", "date", "customer", "due_date"),
        dcdmaker.Array("items", "name", "qty", "unit_price", "total"),
        dcdmaker.Object("summary", "subtotal", "tax", "grand_total"),
    ).
    Run("templates/invoice.dcd")
  • Object(name, fields...) — singleton object, accessed as {{name.field}}
  • Array(name, fields...) — array of objects for <loop>, accessed as {{x.field}}
  • Keys(fields...) — flat keys, no object prefix, accessed as {{field}} directly
  • KeysEx(fields...) — flat keys with typed fields via Field()
  • ObjectEx(name, fields...) — object with typed fields via Field() (type, optional format)
  • ArrayEx(name, fields...) — array with typed fields via Field()

Typed fields with Field():

maker.PredictableKeys(
    dcdmaker.ObjectEx("info",
        dcdmaker.Field("invoice_no", "string"),
        dcdmaker.Field("date", "date-str", "DD-MM-YYYY"),
        dcdmaker.Field("total", "number"),
    ),
    dcdmaker.ArrayEx("items",
        dcdmaker.Field("name", "string"),
        dcdmaker.Field("qty", "number"),
    ),
    dcdmaker.KeysEx(
        dcdmaker.Field("date", "date-str", "DD-MM-YYYY"),
        dcdmaker.Field("total", "number"),
    ),
)
Field usage Prompt output
Field("name", "string") name: string
Field("qty", "number") qty: number
Field("active", "boolean") active: boolean
Field("date", "date-str", "DD-MM-YYYY") date: date-str (DD-MM-YYYY)

Applies to ObjectEx, ArrayEx, KeysEx:

ObjectEx("info",  Field("name", "string"))         // info {name: string}
ArrayEx("items",  Field("qty", "number"))           // items []qty: number
KeysEx(           Field("date", "date-str", "DD-MM-YYYY")) // date: date-str ... (keys)

Additional fields found in the document are written to [object-unpredictable] and [keys-unpredictable] sections.

Retrieving Unpredictable Fields
maker.Run("output.dcd")

for _, obj := range maker.UnpredictableObjects() {
    fmt.Printf("Object: %s (array=%v) fields=%v\n", obj.Name, obj.IsArray, obj.Fields)
}

keys := maker.UnpredictableKeys()
fmt.Println("Additional keys:", keys)

// Raw DCD output
_ = maker.LastResult()

// Which provider/model succeeded (e.g. "gemini:gemini-2.5-flash")
_ = maker.LastProvider()
AddPredictableKeys

Append variable keys without clearing previously set ones:

maker.
    AddPredictableKeys(
        dcdmaker.Object("extra", "notes", "approved_by"),
    )
Fallback by model
maker := dcdmaker.NewMaker(
    // Gemini Pro → retry 3x → Gemini Flash → retry 3x → OpenAI
    dcdmaker.Gemini(dcdmaker.WithModel("gemini-2.5-pro-exp-03-25")),
    dcdmaker.Gemini(dcdmaker.WithModel("gemini-2.5-flash")),
    dcdmaker.OpenAI(dcdmaker.WithOpenAIModel("gpt-4o")),
)

Configuration

Gemini
Option Default Description
WithModel gemini-2.5-flash Model name
WithTemperature 0.5 Temperature (0–1)
WithAPIKey $GEMINI_API_KEY API key
WithTimeout 60s Request timeout
OpenAI
Option Default Description
WithOpenAIModel gpt-4o Model name
WithOpenAIBaseURL Custom base URL (for Ollama, vLLM, etc.)
WithOpenAITemperature 0.5 Temperature (0–1)
WithOpenAIMaxTokens 8192 Max output tokens
WithOpenAIAPIKey $OPENAI_API_KEY API key
WithOpenAITimeout 60s Request timeout

For large documents (28+ pages), use 180s+ timeout: WithTimeout(180*time.Second) or WithOpenAITimeout(180*time.Second)

How It Works

DOCX ──> dcdmaker ──> AI (Gemini / OpenAI) ──> .dcd template
  1. Read — Source document loaded from disk
  2. Parse — DOCX parsed into structured format: layout, margins, fonts, headings, paragraphs
  3. Generate — AI produces DCD template based on structured source, with [style] generated deterministically by code
  4. Validate — Output checked for valid DCD structure
  5. Retry — 3 attempts per provider, fallback to next provider

Output: .dcd Template

[style]
layout=A4
unit=inch
m=1

[title]
title=Invoice

[header]
right={{page}} / {{total}}

[section 0]
name=header
var=info
keys=invoice_no, date, customer

--- BODY ---
<h1>{{info.invoice_no}}</h1>
<p>Date: {{info.date}}</p>
<p>Customer: {{info.customer}}</p>

[section 1]
name=items
var=info, items
keys=title, items.name, items.qty, items.price

--- BODY ---
<table border=1 width=100%>
<loop:row x from items>
  <col>{{x.name}}</col>
  <col align=right>{{x.qty}}</col>
  <col align=right>{{x.price}}</col>
</loop:row>
</table>

[object-unpredictable]
- info=discount, shipping_address

[keys-unpredictable]
- po_number, department

Development

go test ./...
go vet ./...
go build ./...

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BasedOnStyle

type BasedOnStyle struct {
	ID   string
	Name string
}

type BorderInfo

type BorderInfo struct {
	Val   string
	Sz    int
	Space int
	Color string
}

type ContentItem

type ContentItem struct {
	Type      ContentType
	Paragraph *ParsedParagraph
	Table     *ParsedTable
}

type ContentType

type ContentType int
const (
	ContentParagraph ContentType = iota
	ContentTable
)

type CustomStyleDef

type CustomStyleDef struct {
	Name    string
	Type    string
	BasedOn string
	StyleDef
}

type FieldDef

type FieldDef struct {
	Name   string
	Type   string // "string", "number", "boolean", "date-str"
	Format string // optional, used with date-str
}

func Field

func Field(name string, typ string, format ...string) FieldDef

type FontDef

type FontDef struct {
	Family   string
	SizePt   float64
	Color    string
	FromDocx bool
}

type GeminiOption

type GeminiOption func(*geminiConfig)

func WithAPIKey

func WithAPIKey(k string) GeminiOption

func WithModel

func WithModel(m string) GeminiOption

func WithStream

func WithStream(s bool) GeminiOption

func WithTemperature

func WithTemperature(t float64) GeminiOption

func WithTimeout

func WithTimeout(d time.Duration) GeminiOption

type KeyDef

type KeyDef struct {
	Name      string
	Type      VarType
	Fields    []string   // backwards compat, used when FieldDefs is nil
	FieldDefs []FieldDef // takes priority over Fields when set
}

func Array

func Array(name string, fields ...string) KeyDef

func ArrayEx

func ArrayEx(name string, fields ...FieldDef) KeyDef

func Keys

func Keys(fields ...string) KeyDef

func KeysEx

func KeysEx(fields ...FieldDef) KeyDef

func Object

func Object(name string, fields ...string) KeyDef

func ObjectEx

func ObjectEx(name string, fields ...FieldDef) KeyDef

type Maker

type Maker struct {
	// contains filtered or unexported fields
}

func NewMaker

func NewMaker(providers ...Provider) *Maker

func (*Maker) AddPredictableKeys

func (m *Maker) AddPredictableKeys(keys ...KeyDef) *Maker

func (*Maker) Generate

func (m *Maker) Generate() (string, error)

func (*Maker) LastProvider added in v0.2.3

func (m *Maker) LastProvider() string

func (*Maker) LastResult

func (m *Maker) LastResult() string

func (*Maker) MaxRetries

func (m *Maker) MaxRetries(n int) *Maker

func (*Maker) OptionalPrompt

func (m *Maker) OptionalPrompt(p string) *Maker

func (*Maker) PredictableKeys

func (m *Maker) PredictableKeys(keys ...KeyDef) *Maker

func (*Maker) Run

func (m *Maker) Run(output string) error

func (*Maker) Source

func (m *Maker) Source(path string) *Maker

func (*Maker) UnpredictableKeys

func (m *Maker) UnpredictableKeys() []string

func (*Maker) UnpredictableObjects

func (m *Maker) UnpredictableObjects() []UnpredictableObject

type Message

type Message struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

type NoteItem

type NoteItem struct {
	Type   string // "footnote", "endnote", "bookmark", "comment"
	ID     int
	Name   string // bookmark name
	Author string // comment author
	Date   string // comment date
	Body   []ContentItem
}

type OpenAIOption

type OpenAIOption func(*openAIConfig)

func WithOpenAIAPIKey

func WithOpenAIAPIKey(k string) OpenAIOption

func WithOpenAIBaseURL

func WithOpenAIBaseURL(u string) OpenAIOption

func WithOpenAIMaxTokens added in v0.2.3

func WithOpenAIMaxTokens(n int) OpenAIOption

func WithOpenAIModel

func WithOpenAIModel(m string) OpenAIOption

func WithOpenAIStream

func WithOpenAIStream(s bool) OpenAIOption

func WithOpenAITemperature added in v0.2.3

func WithOpenAITemperature(t float64) OpenAIOption

func WithOpenAITimeout added in v0.2.3

func WithOpenAITimeout(d time.Duration) OpenAIOption

type PageLayout

type PageLayout struct {
	WidthInch    float64
	HeightInch   float64
	MarginTop    float64
	MarginRight  float64
	MarginBottom float64
	MarginLeft   float64
	HeaderMargin float64
	FooterMargin float64
	FromDocx     bool
}

type ParsedDocument

type ParsedDocument struct {
	PageLayout     PageLayout
	DefaultFont    FontDef
	LineHeight     float64
	LineRule       string
	Title          string
	Subject        string
	Author         string
	Keywords       string
	Description    string
	Category       string
	ContentStatus  string
	LastModifiedBy string
	Revision       string
	Version        string
	Created        string
	Modified       string
	Language       string
	Application    string
	AppVersion     string
	HeadingStyles  map[int]StyleDef
	Content        []ContentItem
	Sections       []ParsedSection
	AllTables      []ParsedTable
	Notes          []NoteItem
	CustomStyles   []CustomStyleDef
	Mode           string // "semantic" (default) or "lossless"
	Theme          *ThemeData
}

func ParseDOCX

func ParseDOCX(data []byte) (*ParsedDocument, error)

func (*ParsedDocument) FormatForLLM

func (doc *ParsedDocument) FormatForLLM() string

func (*ParsedDocument) GenerateStyleBlock

func (doc *ParsedDocument) GenerateStyleBlock() string

type ParsedHdrFtr

type ParsedHdrFtr struct {
	Type    string // "default", "first", "even"
	Content []ContentItem
}

type ParsedParagraph

type ParsedParagraph struct {
	Runs                []TextRun
	Align               string
	IndentLeft          float64
	IndentRight         float64
	FirstLineIndent     float64
	Hanging             float64
	SpacingBefore       float64
	SpacingAfter        float64
	LineHeight          float64
	LineRule            string
	Bold                bool
	Italic              bool
	FontFamily          string
	FontSizePt          float64
	FontColor           string
	HeadingLevel        int
	IsList              bool
	ListLevel           int
	ListFormat          string
	ListStartOverride   int
	StyleID             string
	StyleName           string
	KeepNext            bool
	KeepLines           bool
	WidowControl        bool
	ContextualSpacing   bool
	SuppressLineNumbers bool
	SuppressHyphenation bool
	TextDirection       string
	BorderTop           *BorderInfo
	BorderBottom        *BorderInfo
	BorderLeft          *BorderInfo
	BorderRight         *BorderInfo
	ShadingFill         string
	PageBreakBefore     bool
	Kinsoku             bool
	WordWrap            bool
	CharSpacingJust     int
	TwoLineOne          bool
	AutoSpaceDE         bool
	AutoSpaceDN         bool
	Bidi                bool
	IsCode              bool
	IsQuote             bool
	Lang                string
	VAlign              string
	TabStops            []TabStopDef
}

type ParsedSection

type ParsedSection struct {
	Layout       PageLayout
	Headers      []ParsedHdrFtr
	Footers      []ParsedHdrFtr
	Content      []ContentItem
	BreakType    string
	ColCount     int
	ColSpace     float64
	PageNumFmt   string
	PageNumStart int
}

type ParsedTable

type ParsedTable struct {
	ID           int
	Grid         []float64
	Rows         []ParsedTableRow
	HasBorders   bool
	BorderTop    *BorderInfo
	BorderBottom *BorderInfo
	BorderLeft   *BorderInfo
	BorderRight  *BorderInfo
	Width        float64
	Alignment    string
	Caption      string
	Summary      string
	Indent       float64
	CellSpacing  float64
	StyleName    string
}

type ParsedTableCell

type ParsedTableCell struct {
	Content       []ContentItem
	GridSpan      int
	RowSpan       int
	VMerge        string
	ShadingFill   string
	BorderTop     *BorderInfo
	BorderBottom  *BorderInfo
	BorderLeft    *BorderInfo
	BorderRight   *BorderInfo
	VAlign        string
	TextDirection string
	NoWrap        bool
}

type ParsedTableRow

type ParsedTableRow struct {
	IsHeader bool
	Cells    []ParsedTableCell
}

type Provider

type Provider interface {
	Name() string
	GenerateWithFile(ctx context.Context, prompt string, filename string, data []byte) (string, error)
	GenerateWithHistory(ctx context.Context, history []Message, prompt string) (string, error)
}

func Gemini

func Gemini(opts ...GeminiOption) Provider

func OpenAI

func OpenAI(opts ...OpenAIOption) Provider

type StyleDef

type StyleDef struct {
	Family        string
	FontEA        string
	FontCS        string
	SizePt        float64
	SizeCS        float64
	Color         string
	Bold          bool
	Italic        bool
	Underline     string
	Strikethrough bool
	SmallCaps     bool
	Uppercase     bool
	SpacingBefore float64
	SpacingAfter  float64
	LineSpacing   float64
	LineRule      string
	Align         string
	IndentLeft    float64
	IndentRight   float64
	IndentFirst   float64
	IndentHanging float64
	BorderTop     string
	BorderBottom  string
	BorderLeft    string
	BorderRight   string
	BorderWidth   int
	BorderColor   string
	BorderStyle   string
	HeadingLevel  int
}

type TabStopDef

type TabStopDef struct {
	Pos    float64
	Align  string
	Leader string
}

type TextRun

type TextRun struct {
	Text             string
	Bold             bool
	Italic           bool
	Underline        string
	Strike           bool
	DStrike          bool
	SuperScript      bool
	SubScript        bool
	FontFamily       string
	FontSizePt       float64
	FontColor        string
	Highlight        string
	SmallCaps        bool
	AllCaps          bool
	Hidden           bool
	CharSpacing      int
	Position         int
	Language         string
	Emphasis         string
	RTL              bool
	NoProof          bool
	CS               bool
	SpecVanish       bool
	Emboss           bool
	Engrave          bool
	Shadow           bool
	Imprint          bool
	Border           string
	Effect           bool
	Animate          bool
	BCs              bool
	ICs              bool
	FontEA           string
	FontCS           string
	SizeCS           float64
	BreakType        string
	IsTab            bool
	IsLineBreak      bool
	IsPageBreak      bool
	IsImage          bool
	IsSym            bool
	SymChar          rune
	IsNoBreakHyphen  bool
	IsSoftHyphen     bool
	IsCarriageReturn bool
	ImageSrc         string
	ImageWidth       float64
	ImageHeight      float64
	ImageAlt         string
	IsField          bool
	FieldType        string
	FieldFormat      string
	FieldName        string
	IsHyperlink      bool
	HyperlinkURL     string
	IsFootnoteRef    bool
	IsEndnoteRef     bool
	NoteID           int
	TextBoxContent   []ContentItem
	IsIns            bool
	IsDel            bool
	InsID            int
	InsAuthor        string
	InsDate          string
	SpacePreserve    bool
}

type ThemeData

type ThemeData struct {
	Bg string
	Fg string
}

type UnpredictableObject

type UnpredictableObject struct {
	Name    string
	Fields  []string
	IsArray bool
}

type VarType

type VarType int
const (
	VarObject VarType = iota
	VarArray
	VarKeys
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL