Skip to content

Commit 04db0c7

Browse files
upgrade substrate_rag.omc to use native substrate_embed + str_similarity
- Drop hand-rolled substrate_embed (shadows the native builtin) - Use native substrate_embed(text, 16) for all document indexing - Add str_similarity demo section (Part 2) showing offline semantic scoring - Remove dependency on examples/lib/text.omc (tokenize no longer needed) - Structure as 3 parts: offline retrieval / str_similarity / RAG+LLM Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9b957cf commit 04db0c7

1 file changed

Lines changed: 62 additions & 94 deletions

File tree

examples/demos/substrate_rag.omc

Lines changed: 62 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,21 @@
11
# substrate_rag.omc
2-
# Phi-Pi-Fibonacci RAG (Retrieval-Augmented Generation) using substrate embeddings.
3-
# Stores documents with substrate-harmonic indexing; retrieves by harmonic distance.
2+
# Phi-Pi-Fibonacci RAG (Retrieval-Augmented Generation) using native substrate_embed.
3+
# The native substrate_embed builtin (no API key, pure math) powers all retrieval.
44

5-
import "examples/lib/text.omc"
65
import "examples/lib/llm.omc"
76
import "examples/lib/cache.omc"
87

98
h MODEL = "claude-opus-4-5"
109
h EMBED_CACHE = lru_new(500)
1110

12-
# ── Phi-Pi-Fib substrate embedding (pure OMC) ──────────────────────────────────
11+
# ── Embedding helpers ─────────────────────────────────────────────────────────
1312

14-
h PHI = 1.6180339887
15-
h PI = 3.14159265358979
16-
h FIB = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
17-
18-
fn substrate_encode_char(c, position) {
19-
h cp = str_len(c)
20-
h fib_idx = position % arr_len(FIB)
21-
h freq = FIB[fib_idx] * PHI
22-
h phase = position * PI / 7.0
23-
h signal = math_sin(freq + phase) * cp
24-
return signal
25-
}
26-
27-
fn substrate_embed(text) {
28-
h cache_key = text
29-
h cached = lru_get(EMBED_CACHE, cache_key)
13+
fn embed_cached(text) {
14+
h cached = lru_get(EMBED_CACHE, text)
3015
if cached != null { return cached }
31-
32-
h tokens = tokenize(text)
33-
h dim = arr_len(FIB)
34-
h embedding = []
35-
h d = 0
36-
while d < dim {
37-
arr_push(embedding, 0.0)
38-
d = d + 1
39-
}
40-
41-
h ti = 0
42-
while ti < arr_len(tokens) {
43-
h token = tokens[ti]
44-
h ci = 0
45-
while ci < str_len(token) {
46-
h char = str_slice(token, ci, ci + 1)
47-
h fib_idx = (ti + ci) % dim
48-
h signal = substrate_encode_char(char, ti * 7 + ci)
49-
embedding[fib_idx] = embedding[fib_idx] + signal
50-
ci = ci + 1
51-
}
52-
ti = ti + 1
53-
}
54-
55-
# L2 normalize
56-
h mag = 0.0
57-
h di = 0
58-
while di < dim {
59-
mag = mag + embedding[di] * embedding[di]
60-
di = di + 1
61-
}
62-
mag = math_sqrt(mag)
63-
if mag > 0.0 {
64-
di = 0
65-
while di < dim {
66-
embedding[di] = embedding[di] / mag
67-
di = di + 1
68-
}
69-
}
70-
71-
lru_put(EMBED_CACHE, cache_key, embedding)
72-
return embedding
16+
h v = substrate_embed(text, 16)
17+
lru_put(EMBED_CACHE, text, v)
18+
return v
7319
}
7420

7521
fn cosine_sim(a, b) {
@@ -91,7 +37,7 @@ fn docstore_new() {
9137
}
9238

9339
fn docstore_add(store, text, meta) {
94-
h embedding = substrate_embed(text)
40+
h embedding = embed_cached(text)
9541
arr_push(store["docs"], text)
9642
arr_push(store["embeddings"], embedding)
9743
h m = meta
@@ -100,15 +46,15 @@ fn docstore_add(store, text, meta) {
10046
}
10147

10248
fn docstore_search(store, query, top_k) {
103-
h query_embed = substrate_embed(query)
49+
h query_embed = embed_cached(query)
10450
h scores = []
10551
h i = 0
10652
while i < arr_len(store["docs"]) {
10753
h sim = cosine_sim(query_embed, store["embeddings"][i])
10854
arr_push(scores, {idx: i, score: sim})
10955
i = i + 1
11056
}
111-
# sort descending
57+
# bubble-sort descending
11258
h n = arr_len(scores)
11359
h si = 0
11460
while si < n {
@@ -144,33 +90,25 @@ fn docstore_search(store, query, top_k) {
14490
fn rag_answer(store, question, top_k, model) {
14591
h m = model
14692
if m == null { m = MODEL }
147-
14893
h retrieved = docstore_search(store, question, top_k)
149-
15094
h context_parts = []
15195
h i = 0
15296
while i < arr_len(retrieved) {
15397
arr_push(context_parts, str_concat(
154-
"[Doc ", to_str(i + 1), " | similarity: ", to_str(retrieved[i]["score"]), "]\n",
98+
"[Doc ", to_str(i + 1), " | sim=", to_str(retrieved[i]["score"]), "]\n",
15599
retrieved[i]["text"]
156100
))
157101
i = i + 1
158102
}
159103
h context = arr_join(context_parts, "\n\n")
160-
161104
h sys = "You are a helpful assistant. Answer questions based only on the provided context. Be concise."
162105
h prompt = str_concat(
163106
"Context:\n", context, "\n\n",
164107
"Question: ", question, "\n\n",
165108
"Answer based only on the context above."
166109
)
167-
168110
h answer = llm_call(prompt, m, sys)
169-
return {
170-
answer: answer,
171-
retrieved: retrieved,
172-
question: question
173-
}
111+
return {answer: answer, retrieved: retrieved, question: question}
174112
}
175113

176114
# ── Knowledge base ────────────────────────────────────────────────────────────
@@ -183,7 +121,7 @@ h DOCUMENTS = [
183121
meta: {source: "OMC intro", topic: "language"}
184122
},
185123
{
186-
text: "The phi-pi-fibonacci substrate uses Fibonacci numbers [1,1,2,3,5,8,13,21,...], the golden ratio φ=1.618..., and π=3.14159... to create harmonic positional embeddings. These beat sinusoidal encodings in transformerless architectures.",
124+
text: "The phi-pi-fibonacci substrate uses Fibonacci numbers [1,1,2,3,5,8,13,21,...], the golden ratio phi=1.618..., and pi=3.14159... to create harmonic positional embeddings. These beat sinusoidal encodings in transformerless architectures.",
187125
meta: {source: "substrate docs", topic: "math"}
188126
},
189127
{
@@ -195,7 +133,7 @@ h DOCUMENTS = [
195133
meta: {source: "builtins ref", topic: "meta"}
196134
},
197135
{
198-
text: "par_map(fn, array) runs fn on each element of array in parallel. OMC also provides par_filter and par_reduce. These are sequential fallbacks since Value uses Rc/RefCell internally.",
136+
text: "par_map(fn, array) runs fn on each element of array in parallel. OMC also provides par_filter and par_reduce. These enable fast batch LLM calls via batch_llm_call.",
199137
meta: {source: "stdlib ref", topic: "parallel"}
200138
},
201139
{
@@ -212,42 +150,72 @@ h DOCUMENTS = [
212150
}
213151
]
214152

215-
# Index documents
153+
# Index documents using native substrate_embed (no API key, pure math)
154+
print("=== Substrate RAG demo ===")
155+
print("Indexing documents with native substrate_embed (offline, no API key)...")
216156
h i = 0
217157
while i < arr_len(DOCUMENTS) {
218158
h doc = DOCUMENTS[i]
219159
docstore_add(KB, doc["text"], doc["meta"])
220160
i = i + 1
221161
}
222-
223-
print(str_concat("Indexed ", to_str(arr_len(DOCUMENTS)), " documents with substrate embeddings"))
162+
print(str_concat("Indexed ", to_str(arr_len(DOCUMENTS)), " documents"))
224163
print("")
225164

226-
# ── Demo queries ──────────────────────────────────────────────────────────────
165+
# ── Part 1: Pure substrate retrieval (offline) ────────────────────────────────
227166

228-
h QUESTIONS = [
167+
print("--- Part 1: Offline substrate retrieval ---")
168+
h QUERIES = [
229169
"How does OMC call Claude?",
230170
"What is the phi-pi-fibonacci substrate?",
231171
"Can OMC use Python libraries?",
232-
"How does recursive self-improvement work in OMC?",
233-
"What is Prometheus in OMC?"
172+
"How does recursive self-improvement work in OMC?"
234173
]
235174

236175
h qi = 0
237-
while qi < arr_len(QUESTIONS) {
238-
h q = QUESTIONS[qi]
176+
while qi < arr_len(QUERIES) {
177+
h q = QUERIES[qi]
178+
h retrieved = docstore_search(KB, q, 1)
179+
h top = retrieved[0]
239180
print(str_concat("Q: ", q))
181+
print(str_concat(" Best match (sim=", to_str(top["score"]), "): '", str_slice(top["text"], 0, 80), "...'"))
182+
print("")
183+
qi = qi + 1
184+
}
240185

241-
# First show substrate retrieval
242-
h retrieved = docstore_search(KB, q, 2)
243-
print(str_concat(" Retrieved: '", str_slice(retrieved[0]["text"], 0, 60), "...' (sim=", to_str(retrieved[0]["score"]), ")"))
186+
# ── Part 2: str_similarity demo (uses same substrate math) ───────────────────
244187

245-
# Then get RAG answer
188+
print("--- Part 2: str_similarity (same substrate math, no API) ---")
189+
h pairs = [
190+
["phi-pi-fibonacci harmonic embeddings", "Fibonacci golden ratio substrate math"],
191+
["phi-pi-fibonacci harmonic embeddings", "Python neural network PyTorch training"],
192+
["OMC self-hosting language", "OMC recursive self-improvement"],
193+
["OMC self-hosting language", "NFL football scores statistics"]
194+
]
195+
h pi2 = 0
196+
while pi2 < arr_len(pairs) {
197+
h pair = pairs[pi2]
198+
h sim = str_similarity(pair[0], pair[1])
199+
print(str_concat(" '", str_slice(pair[0], 0, 35), "' vs '", str_slice(pair[1], 0, 35), "' => ", to_str(sim)))
200+
pi2 = pi2 + 1
201+
}
202+
print("")
203+
204+
# ── Part 3: Full RAG with LLM answer ─────────────────────────────────────────
205+
206+
print("--- Part 3: RAG answer via LLM ---")
207+
h LLM_QUESTIONS = [
208+
"How does recursive self-improvement work in OMC?",
209+
"What is Prometheus in OMC?"
210+
]
211+
h lqi = 0
212+
while lqi < arr_len(LLM_QUESTIONS) {
213+
h q = LLM_QUESTIONS[lqi]
214+
print(str_concat("Q: ", q))
246215
h result = rag_answer(KB, q, 2, null)
247-
print(str_concat(" A: ", str_slice(result["answer"], 0, 120)))
216+
print(str_concat("A: ", str_slice(result["answer"], 0, 200)))
248217
print("")
249-
250-
qi = qi + 1
218+
lqi = lqi + 1
251219
}
252220

253-
print("=== Substrate RAG demo complete ===")
221+
print("=== Substrate RAG complete ===")

0 commit comments

Comments
 (0)