Skip to content

gemma example: local agent loop with Gemma over Ollama, vector recall, and the verification barrier - #519

Merged
gerardrecinto merged 1 commit into
masterfrom
gemma-ollama-example
Oct 8, 2026
Merged

gerardrecinto merged 1 commit into
masterfrom
gemma-ollama-example

Conversation

@gerardrecinto

Copy link
Copy Markdown
Collaborator

Summary

  • Adds examples/gemma_ollama: a local agent loop with Gemma (gemma3:4b) and embeddinggemma through Ollama, and Joltrin embedded in the same Go process. No remote database, no network hop beyond localhost Ollama.
  • Gemma proposes actions. Joltrin retrieves context (ai/vector), enforces ordering (verify.Workflow), and commits state (database.Database transactions).
  • App code validates the JSON (shape, known fields, allowed step, payload size) before the barrier. The barrier only enforces preconditions and precedence.
  • The model is never offered human_approve. Only the application calls it, so a model cannot approve its own work.

Flow

flowchart LR
    A[App] --> G[Gemma via Ollama]
    G --> S[App schema check]
    S -->|valid| B[verify barrier<br/>CheckSafety]
    S -->|invalid| G
    B -->|allowed| T[ACID commit<br/>vector store + storage]
    B -->|violation| G
Loading

What the demo does

  1. Embeds three facts in one transaction and recalls the rollback fact for the question.
  2. Act 1: Gemma drafts a note from the retrieved facts. Committed.
  3. Act 2: Gemma is told to publish before approval. The barrier blocks every attempt and the log row count does not change.
  4. Act 3: the app records the human approval, then publish_note commits.

Commit order: the read-only CheckSafety runs first, before any embedding or transaction work. The data commit comes next, then CheckAndCommitIdempotent records the step. A crash between the last two leaves a row with no trace entry, which fails closed: later steps stay blocked until the step is recorded again.

Testing

Offline (scripted Ollama server, real vector store and barrier), also run in CI by the new gemma-example workflow:

  • go test ./examples/gemma_ollama -race -count=1 passes.
  • Cases: schema table (8 inputs), recall ranking, schema rejection then recovery, publish blocked until human approval, model cannot approve itself, full three-act demo.
  • Removing the CheckSafety call makes TestBarrierBlocksPublishUntilHumanApproves and TestDemoWithScriptedModel fail.

Live, against local Ollama with gemma3:4b and embeddinggemma (Apple laptop, JOLTRIN_OLLAMA_LIVE=1 go test ./examples/gemma_ollama -run TestLiveGemma -v), 3 runs, 3 passes, about 11 seconds each:

recall f3 score=0.692
recall f1 score=0.303

act 1: draft a note
  attempt 1 committed step "draft_note"

act 2: publish before approval
  attempt 1 blocked by barrier: ... State "approved" has not been established in this run ...
  attempt 2 blocked by barrier: ...
  attempt 3 blocked by barrier: ...
  committed=false rows before=1 after=1

act 3: human approves, then publish
  attempt 1 committed step "publish_note"
  log rows: 2

The live test is skipped unless JOLTRIN_OLLAMA_LIVE=1, so CI does not need a model.

Tips

  • Cap context: num_ctx: 4096 and 2 to 4 retrieved chunks.
  • Keep the embedding model separate from the chat model. embeddinggemma is 768 dims, which matches OllamaEmbedder.Dim() (hardcoded to 768).
  • Embed first, then write a batch in one transaction to keep write locks short.

Thanks,
Gerard Recinto

@gerardrecinto gerardrecinto self-assigned this Oct 8, 2026
@gerardrecinto
gerardrecinto enabled auto-merge (squash) October 8, 2026 20:54
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown

Gemini PR Review

Reviewed commit: e6cc9562f972e2f2ca2aad98627ce35ee8e2f60e
Verdict: PASS

  • Correctness/Security: In examples/gemma_ollama/main.go, the commit method's two-phase commit (database write followed by workflow trace update) is designed to "fail-closed." If the process terminates between these two operations, the data may exist in the vector store, but the workflow step will not be recorded in the trace, thus keeping later steps blocked. This is explicitly noted in the code as a fail-closed mechanism, which prioritizes security and integrity over potential data inconsistency, and is an acceptable design given the problem domain.

@gerardrecinto
gerardrecinto merged commit 9887f1c into master Oct 8, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant