afaceuser09 commited on
Commit
70372cf
·
verified ·
1 Parent(s): b36e785

Update reasoning_engine.py

Browse files
Files changed (1) hide show
  1. reasoning_engine.py +372 -199
reasoning_engine.py CHANGED
@@ -1,24 +1,30 @@
1
  """
2
  Infinity GRM - Reasoning Engine
3
  ================================
4
-
5
- Standalone cognitive/reasoning layer.
6
-
7
- Responsibilities:
8
- - Problem understanding and planning
9
- - Structured reasoning
10
- - Evidence analysis
11
- - Verification / critique
12
- - Experience retrieval ("learning from solved problems")
13
- - Final response synthesis
14
-
15
- The model is reused across all passes so the system does not create a
16
- separate, weaker "reasoning model".
17
-
18
- Important:
19
- The <think> block is a concise reasoning summary / decision trace.
20
- It is deliberately bounded rather than exposing unrestricted private
21
- chain-of-thought.
 
 
 
 
 
 
22
  """
23
 
24
  import os
@@ -35,21 +41,188 @@ import torch
35
  from sentence_transformers import SentenceTransformer
36
  from transformers import AutoTokenizer, AutoModelForCausalLM, AutoConfig
37
 
38
-
39
  logger = logging.getLogger("infinitygrm.reasoning")
40
 
41
  MODEL_NAME = os.getenv("GRM_MODEL", "Qwen/Qwen2.5-7B-Instruct")
42
  MEMORY_DB = Path(os.getenv("GRM_MEMORY_DB", "./grm_experience.sqlite3"))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
- STATE: Dict[str, Any] = {}
 
 
 
 
 
 
 
 
 
 
45
 
 
46
 
47
- # ---------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  # MODEL
49
- # ---------------------------------------------------------------------
 
50
 
51
  def initialize_model():
52
- """Load the language model and embedding model once."""
53
  if STATE.get("model") is not None:
54
  return
55
 
@@ -85,23 +258,16 @@ def initialize_model():
85
  )
86
 
87
  initialize_memory()
88
-
89
- logger.info("Reasoning engine initialized on %s", device)
90
 
91
 
92
- # ---------------------------------------------------------------------
93
  # EXPERIENCE MEMORY
94
- # ---------------------------------------------------------------------
95
 
96
- def initialize_memory():
97
- """Create a persistent experience store.
98
 
99
- This is retrieval-based learning. It lets the model reuse useful
100
- prior solutions without pretending that the base model's weights
101
- have been retrained after every question.
102
- """
103
  MEMORY_DB.parent.mkdir(parents=True, exist_ok=True)
104
-
105
  with sqlite3.connect(MEMORY_DB) as db:
106
  db.execute(
107
  """
@@ -125,17 +291,11 @@ def _embed(text: str) -> np.ndarray:
125
  [text],
126
  normalize_embeddings=True,
127
  convert_to_numpy=True,
 
128
  )[0]
129
 
130
 
131
- def save_experience(
132
- query: str,
133
- plan: str,
134
- analysis: str,
135
- answer: str,
136
- quality: float = 1.0,
137
- ):
138
- """Store a successful solution for later retrieval."""
139
  try:
140
  with sqlite3.connect(MEMORY_DB) as db:
141
  db.execute(
@@ -144,14 +304,7 @@ def save_experience(
144
  (query, plan, analysis, answer, quality, created)
145
  VALUES (?, ?, ?, ?, ?, ?)
146
  """,
147
- (
148
- query,
149
- plan,
150
- analysis,
151
- answer,
152
- float(quality),
153
- time.time(),
154
- ),
155
  )
156
  db.commit()
157
  except Exception as exc:
@@ -159,7 +312,6 @@ def save_experience(
159
 
160
 
161
  def retrieve_experiences(query: str, top_k: int = 3) -> List[Dict[str, Any]]:
162
- """Retrieve semantically similar prior problem-solving experiences."""
163
  try:
164
  with sqlite3.connect(MEMORY_DB) as db:
165
  rows = db.execute(
@@ -177,104 +329,106 @@ def retrieve_experiences(query: str, top_k: int = 3) -> List[Dict[str, Any]]:
177
 
178
  qv = _embed(query)
179
  scored = []
180
-
181
  for row in rows:
182
- # Re-embed only the stored query. For a production system,
183
- # persist embeddings in a vector DB or serialized index.
184
  rv = _embed(row[1])
185
- score = float(np.dot(qv, rv))
186
- scored.append((score, row))
187
-
188
  scored.sort(key=lambda x: x[0], reverse=True)
189
 
190
- results = []
191
- for score, row in scored[:top_k]:
192
- results.append(
193
- {
194
- "similarity": score,
195
- "query": row[1],
196
- "plan": row[2],
197
- "analysis": row[3],
198
- "answer": row[4],
199
- "quality": row[5],
200
- }
201
- )
202
-
203
- return results
204
-
205
  except Exception as exc:
206
  logger.warning("Experience retrieval failed: %s", exc)
207
  return []
208
 
209
 
210
- # ---------------------------------------------------------------------
211
- # GENERATION
212
- # ---------------------------------------------------------------------
213
 
214
- def generate(
215
- messages: List[Dict[str, str]],
216
- max_new_tokens: int = 1024,
217
- temperature: float = 0.15,
218
- ) -> str:
219
  """Run one model pass."""
220
  initialize_model()
221
 
222
  tokenizer = STATE["tokenizer"]
223
  model = STATE["model"]
224
 
225
- prompt = tokenizer.apply_chat_template(
226
- messages,
227
- tokenize=False,
228
- add_generation_prompt=True,
229
- )
230
-
231
  inputs = tokenizer(prompt, return_tensors="pt")
232
- inputs = {
233
- k: v.to(model.device)
234
- for k, v in inputs.items()
 
 
 
235
  }
 
 
 
 
236
 
237
  with torch.no_grad():
238
- output = model.generate(
239
- **inputs,
240
- max_new_tokens=max_new_tokens,
241
- temperature=temperature,
242
- top_p=0.90,
243
- repetition_penalty=1.05,
244
- do_sample=True,
245
- pad_token_id=tokenizer.eos_token_id,
246
- )
247
 
248
  new_tokens = output[0][inputs["input_ids"].shape[1]:]
 
 
249
 
250
- return tokenizer.decode(
251
- new_tokens,
252
- skip_special_tokens=True,
253
- ).strip()
254
 
255
 
256
  def clean_think_block(text: str) -> str:
257
- """Normalize a model-generated <think> block."""
 
 
 
 
 
258
  text = text.strip()
 
 
 
 
 
259
 
260
- if not text.startswith("<think>"):
261
- text = "<think>\n" + text
 
262
 
263
- if "</think>" not in text:
264
- text += "\n</think>"
265
 
266
- return text
 
 
 
 
 
 
 
 
267
 
268
 
269
- # ---------------------------------------------------------------------
270
  # COGNITIVE PASSES
271
- # ---------------------------------------------------------------------
272
 
273
  PLANNER_SYSTEM = r"""
274
  You are the planning component of Infinity GRM.
275
 
276
- Your job is to understand the user's problem and produce a compact,
277
- high-quality execution plan.
 
278
 
279
  You must:
280
  - identify the actual task;
@@ -287,7 +441,11 @@ You must:
287
 
288
  Return:
289
  <think>
290
- A concise reasoning summary describing the key decisions and plan.
 
 
 
 
291
  </think>
292
 
293
  Then return JSON with:
@@ -299,104 +457,84 @@ Then return JSON with:
299
  "verification": ["..."],
300
  "difficulty": "easy|medium|hard|expert"
301
  }
302
-
303
- Do not put unrestricted private chain-of-thought in the response.
304
  """
305
 
306
  ANALYST_SYSTEM = r"""
307
  You are the evidence-analysis component of Infinity GRM.
308
 
309
- You receive:
310
- 1. the user's question,
311
- 2. a reasoning plan,
312
- 3. retrieved web evidence,
313
- 4. relevant prior experiences.
 
 
 
 
 
 
 
 
 
 
314
 
315
- Analyze the evidence rather than blindly trusting it.
 
316
 
317
- Check:
318
- - relevance;
319
- - consistency;
320
- - contradictions;
321
- - unsupported claims;
322
- - missing information;
323
- - calculations;
324
- - assumptions;
325
- - whether the requested conclusion actually follows.
326
 
327
  Return:
328
  <think>
329
- A concise reasoning summary of the evidence evaluation and verification.
 
 
 
 
330
  </think>
331
 
332
- Then provide a structured analysis suitable for a final answer.
333
  """
334
 
335
  FINAL_SYSTEM = r"""
336
- You are the final response component of Infinity GRM.
337
 
338
- Use the supplied plan, analysis, evidence, and conversation context.
339
- Answer the user directly.
340
-
341
- Requirements:
342
- - be accurate;
343
- - distinguish evidence from inference;
344
- - do not invent missing facts;
345
- - use web evidence when supplied;
346
- - preserve important uncertainty;
347
- - explain difficult concepts clearly;
348
- - for code, produce complete usable code when requested;
349
- - do not mention internal architecture unless relevant.
350
-
351
- The response must begin with:
352
 
 
353
  <think>
354
- A concise reasoning summary of the approach and verification.
 
 
 
355
  </think>
356
 
357
- Then provide the final answer.
358
-
359
- The <think> section is a bounded decision summary, not unrestricted
360
- private chain-of-thought.
361
  """
362
 
363
 
364
  def plan(query: str, history: List[Dict[str, str]]) -> Dict[str, Any]:
365
- """First reasoning pass: decide what the system needs to do."""
366
  experiences = retrieve_experiences(query, top_k=3)
367
-
368
- memory_text = "\n\n".join(
369
- f"PRIOR EXPERIENCE {i+1}\n"
370
- f"Problem: {x['query']}\n"
371
- f"Approach: {x['plan']}\n"
372
- f"Analysis: {x['analysis'][:1500]}"
373
- for i, x in enumerate(experiences)
374
- )
375
 
376
  messages = [
377
  {"role": "system", "content": PLANNER_SYSTEM},
378
  {
379
  "role": "user",
380
  "content": (
381
- f"CONVERSATION:\n{json.dumps(history[-8:], ensure_ascii=False)}\n\n"
382
- f"USER QUESTION:\n{query}\n\n"
383
- f"RELEVANT PRIOR EXPERIENCES:\n{memory_text or 'None'}\n\n"
384
  f"RELEVANT REASONING DEMONSTRATIONS:\n{_format_reasoning_examples(query, top_k=8)}"
385
  ),
386
  },
387
  ]
388
 
389
- raw = generate(messages, max_new_tokens=700)
390
- return _parse_plan(raw, experiences)
391
-
392
-
393
- def _parse_plan(raw: str, experiences: List[Dict[str, Any]]) -> Dict[str, Any]:
394
- think = ""
395
- match = re.search(r"<think>(.*?)</think>", raw, re.S | re.I)
396
- if match:
397
- think = match.group(1).strip()
398
-
399
- json_match = re.search(r"\{.*\}", raw, re.S)
400
 
401
  if json_match:
402
  try:
@@ -408,24 +546,18 @@ def _parse_plan(raw: str, experiences: List[Dict[str, Any]]) -> Dict[str, Any]:
408
  pass
409
 
410
  return {
411
- "think": think or "The planner could not produce structured JSON.",
412
- "task": raw,
413
  "requires_web": False,
414
  "search_queries": [],
415
- "steps": [],
416
- "verification": [],
417
  "difficulty": "hard",
418
  "experiences": experiences,
419
  }
420
 
421
 
422
- def analyze(
423
- query: str,
424
- plan_data: Dict[str, Any],
425
- evidence: str,
426
- history: List[Dict[str, str]],
427
- ) -> str:
428
- """Second reasoning pass: analyze tool output and verify it."""
429
  messages = [
430
  {"role": "system", "content": ANALYST_SYSTEM},
431
  {
@@ -439,10 +571,24 @@ def analyze(
439
  ),
440
  },
441
  ]
 
442
 
443
- return clean_think_block(
444
- generate(messages, max_new_tokens=1400)
445
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
446
 
447
 
448
  def final_answer(
@@ -451,8 +597,14 @@ def final_answer(
451
  analysis: str,
452
  evidence: str,
453
  history: List[Dict[str, str]],
 
454
  ) -> str:
455
- """Final reasoning/synthesis pass."""
 
 
 
 
 
456
  messages = [
457
  {"role": "system", "content": FINAL_SYSTEM},
458
  {
@@ -460,16 +612,39 @@ def final_answer(
460
  "content": (
461
  f"QUESTION:\n{query}\n\n"
462
  f"PLAN:\n{json.dumps(plan_data, indent=2)}\n\n"
463
- f"ANALYSIS:\n{analysis[:16000]}\n\n"
 
464
  f"EVIDENCE:\n{evidence[:20000]}\n\n"
465
- f"HISTORY:\n{json.dumps(history[-8:], ensure_ascii=False)}"
 
466
  ),
467
  },
468
  ]
 
469
 
470
- return clean_think_block(
471
- generate(messages, max_new_tokens=2048)
472
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
 
474
 
475
  def learn_from_result(
@@ -479,7 +654,6 @@ def learn_from_result(
479
  answer: str,
480
  quality: float = 1.0,
481
  ):
482
- """Persist a successful solution for future retrieval."""
483
  save_experience(
484
  query=query,
485
  plan=json.dumps(plan_data, ensure_ascii=False),
@@ -493,8 +667,7 @@ def initialize():
493
  initialize_model()
494
 
495
 
496
- REASONING_EXAMPLES = REASONING_EXAMPLES
497
-
498
  if __name__ == "__main__":
499
  initialize()
500
- print("Infinity GRM reasoning engine initialized.")
 
 
1
  """
2
  Infinity GRM - Reasoning Engine
3
  ================================
4
+ Standalone cognitive/reasoning layer for Infinity GRM.
5
+
6
+ Features
7
+ --------
8
+ - Qwen2.5-7B-Instruct reasoning model
9
+ - 700 structured reasoning demonstrations by default
10
+ - Semantic retrieval of relevant demonstrations
11
+ - Planning -> analysis -> verification -> final synthesis
12
+ - Persistent SQLite experience memory
13
+ - Optional detailed, user-visible reasoning TRACE (not raw hidden CoT)
14
+ - Backward-compatible plan()/analyze()/final_answer() API
15
+
16
+ Environment
17
+ -----------
18
+ GRM_MODEL=Qwen/Qwen2.5-7B-Instruct
19
+ GRM_EXAMPLE_TARGET=700 # clamped to 500..1000
20
+ GRM_MEMORY_DB=./grm_experience.sqlite3
21
+ GRM_SHOW_REASONING_TRACE=1 # default enabled for detailed trace output
22
+
23
+ Important
24
+ ---------
25
+ The demonstration library is structured training-style material used at
26
+ inference time. It does not change the neural weights of the base model.
27
+ For model-weight improvement, use a separate SFT/QLoRA training pipeline.
28
  """
29
 
30
  import os
 
41
  from sentence_transformers import SentenceTransformer
42
  from transformers import AutoTokenizer, AutoModelForCausalLM, AutoConfig
43
 
 
44
  logger = logging.getLogger("infinitygrm.reasoning")
45
 
46
  MODEL_NAME = os.getenv("GRM_MODEL", "Qwen/Qwen2.5-7B-Instruct")
47
  MEMORY_DB = Path(os.getenv("GRM_MEMORY_DB", "./grm_experience.sqlite3"))
48
+ EXAMPLE_TARGET = max(500, min(1000, int(os.getenv("GRM_EXAMPLE_TARGET", "700"))))
49
+ SHOW_REASONING_TRACE = os.getenv("GRM_SHOW_REASONING_TRACE", "1").lower() not in {"0", "false", "no"}
50
+
51
+ STATE: Dict[str, Any] = {
52
+ "model": None,
53
+ "tokenizer": None,
54
+ "embed_model": None,
55
+ "device": None,
56
+ "reasoning_example_embeddings": None,
57
+ }
58
+
59
+
60
+ # =====================================================================
61
+ # STRUCTURED REASONING DEMONSTRATION LIBRARY
62
+ # =====================================================================
63
+
64
+ _REASONING_SKILLS = [
65
+ ("mathematics", "algebra", "isolate variables, preserve equality, check by substitution"),
66
+ ("mathematics", "geometry", "identify the governing geometric relationship, substitute known quantities, verify units"),
67
+ ("mathematics", "probability", "define the sample space, identify independence/dependence, compute and sanity-check probabilities"),
68
+ ("mathematics", "statistics", "identify the estimator or test, state assumptions, calculate, interpret uncertainty"),
69
+ ("mathematics", "calculus", "identify the derivative/integral rule, apply it carefully, verify with boundary or dimensional checks"),
70
+ ("algorithms", "complexity", "identify the dominant operation, count repeated work, derive asymptotic time and space complexity"),
71
+ ("algorithms", "sorting", "choose an algorithm based on constraints, preserve correctness invariants, analyze complexity"),
72
+ ("algorithms", "graphs", "model entities as vertices and relationships as edges, choose traversal/shortest-path method, verify reachability"),
73
+ ("algorithms", "dynamic programming", "define state, transition, base case, evaluation order, and prove that states cover all cases"),
74
+ ("algorithms", "greedy methods", "define a locally optimal choice, establish the invariant/exchange argument, then verify feasibility"),
75
+ ("coding", "Python debugging", "reproduce the failure, inspect the smallest relevant state, identify the root cause, patch and retest"),
76
+ ("coding", "data structures", "identify access/update requirements, select an appropriate structure, define invariants and complexity"),
77
+ ("coding", "API design", "define inputs/outputs/errors, preserve contracts, validate data, and design deterministic behavior"),
78
+ ("coding", "concurrency", "identify shared state, define synchronization boundaries, avoid races/deadlocks, and test interleavings"),
79
+ ("coding", "optimization", "measure the bottleneck, improve the dominant cost, preserve semantics, and benchmark before/after"),
80
+ ("coding", "machine learning", "separate data/model/objective/evaluation, identify leakage risks, train, validate, and test independently"),
81
+ ("science", "physics", "translate the situation into variables and laws, keep units consistent, solve symbolically, then sanity-check"),
82
+ ("science", "chemistry", "identify substances and governing conservation laws, balance the reaction/model, calculate, and check stoichiometry"),
83
+ ("science", "biology", "identify the mechanism, distinguish correlation from causation, connect evidence to the proposed biological process"),
84
+ ("engineering", "systems", "decompose components and interfaces, identify bottlenecks/failure modes, design controls and verify requirements"),
85
+ ("engineering", "electronics", "define voltage/current/power relationships, inspect component constraints, calculate worst case, verify margins"),
86
+ ("logic", "deduction", "translate statements into premises, derive consequences, test alternatives, and distinguish valid inference from assumption"),
87
+ ("logic", "constraint solving", "list variables/domains/constraints, propagate restrictions, branch only when needed, verify every constraint"),
88
+ ("software engineering", "architecture", "identify requirements and boundaries, choose components/interfaces, evaluate tradeoffs, and define failure handling"),
89
+ ("software engineering", "testing", "identify observable behavior, partition cases, include edge cases, assert invariants, and test regressions"),
90
+ ("software engineering", "security review", "map trust boundaries, identify attack surfaces, validate inputs/authorization, and verify mitigations"),
91
+ ]
92
+
93
+ _VARIANTS = [
94
+ "direct solution with explicit assumptions",
95
+ "edge-case-heavy solution",
96
+ "debugging-oriented solution",
97
+ "optimization-oriented solution",
98
+ "verification-oriented solution",
99
+ "comparison of two plausible approaches",
100
+ "failure-analysis and correction",
101
+ "design followed by a validation plan",
102
+ "symbolic derivation followed by a numerical sanity check",
103
+ "algorithm selection followed by complexity analysis",
104
+ ]
105
+
106
+
107
+ def _build_reasoning_examples(target: int = EXAMPLE_TARGET) -> List[Dict[str, Any]]:
108
+ """Create a deterministic library of structured reasoning demonstrations.
109
+
110
+ These are inference-time demonstrations rather than weight updates. The
111
+ generator deliberately stores reasoning as concise, inspectable steps,
112
+ not unrestricted hidden chain-of-thought.
113
+ """
114
+ examples: List[Dict[str, Any]] = []
115
+ idx = 0
116
+ skill_count = len(_REASONING_SKILLS)
117
+
118
+ while len(examples) < target:
119
+ domain, skill, principle = _REASONING_SKILLS[idx % skill_count]
120
+ variant = _VARIANTS[(idx // skill_count) % len(_VARIANTS)]
121
+ difficulty = ("medium", "hard", "expert")[(idx // (skill_count * 3)) % 3]
122
+
123
+ problem = (
124
+ f"Solve a {skill} problem using a {variant} approach. "
125
+ f"The solution must apply the core principle: {principle}."
126
+ )
127
+
128
+ steps = [
129
+ f"Identify the exact {skill} task and separate requirements from assumptions.",
130
+ f"Apply the governing principle: {principle}.",
131
+ "Work through the relevant intermediate states without skipping constraint checks.",
132
+ "Inspect edge cases, contradictions, units, invariants, or boundary conditions as applicable.",
133
+ "Produce the solution and independently verify that it satisfies the original requirements.",
134
+ ]
135
+
136
+ verification = [
137
+ "Check that every stated constraint is satisfied.",
138
+ "Check for an unstated assumption that could change the result.",
139
+ "Use an independent sanity check where possible.",
140
+ ]
141
+
142
+ solution = (
143
+ f"Use the {skill} method appropriate to the stated constraints; explicitly state assumptions, "
144
+ "derive the result in ordered steps, then verify the result against the original problem."
145
+ )
146
 
147
+ examples.append({
148
+ "id": idx + 1,
149
+ "domain": domain,
150
+ "skill": skill,
151
+ "difficulty": difficulty,
152
+ "problem": problem,
153
+ "reasoning_trace": steps,
154
+ "verification": verification,
155
+ "solution": solution,
156
+ })
157
+ idx += 1
158
 
159
+ return examples
160
 
161
+
162
+ # IMPORTANT: this is the actual definition that was missing in the broken file.
163
+ REASONING_EXAMPLES: List[Dict[str, Any]] = _build_reasoning_examples(EXAMPLE_TARGET)
164
+
165
+
166
+ def _format_reasoning_examples(query: str, top_k: int = 6) -> str:
167
+ """Return the most relevant structured demonstrations for a query."""
168
+ if not REASONING_EXAMPLES:
169
+ return "No demonstrations available."
170
+
171
+ embed_model = STATE.get("embed_model")
172
+ if embed_model is None:
173
+ # Safe fallback before model initialization.
174
+ selected = REASONING_EXAMPLES[:top_k]
175
+ else:
176
+ try:
177
+ if STATE.get("reasoning_example_embeddings") is None:
178
+ texts = [
179
+ f"{x['domain']} {x['skill']} {x['problem']} {x['solution']}"
180
+ for x in REASONING_EXAMPLES
181
+ ]
182
+ STATE["reasoning_example_embeddings"] = embed_model.encode(
183
+ texts,
184
+ normalize_embeddings=True,
185
+ convert_to_numpy=True,
186
+ show_progress_bar=False,
187
+ )
188
+
189
+ qv = _embed(query)
190
+ matrix = STATE["reasoning_example_embeddings"]
191
+ scores = matrix @ qv
192
+ indices = np.argsort(scores)[::-1][:top_k]
193
+ selected = [REASONING_EXAMPLES[int(i)] for i in indices]
194
+ except Exception as exc:
195
+ logger.warning("Reasoning example retrieval failed: %s", exc)
196
+ selected = REASONING_EXAMPLES[:top_k]
197
+
198
+ blocks = []
199
+ for ex in selected:
200
+ blocks.append(
201
+ "EXAMPLE {id} | {domain}/{skill} | difficulty={difficulty}\n"
202
+ "Problem pattern: {problem}\n"
203
+ "Reasoning steps:\n- {steps}\n"
204
+ "Verification:\n- {verification}\n"
205
+ "Solution pattern: {solution}".format(
206
+ id=ex["id"],
207
+ domain=ex["domain"],
208
+ skill=ex["skill"],
209
+ difficulty=ex["difficulty"],
210
+ problem=ex["problem"],
211
+ steps="\n- ".join(ex["reasoning_trace"]),
212
+ verification="\n- ".join(ex["verification"]),
213
+ solution=ex["solution"],
214
+ )
215
+ )
216
+ return "\n\n".join(blocks)
217
+
218
+
219
+ # =====================================================================
220
  # MODEL
221
+ # =====================================================================
222
+
223
 
224
  def initialize_model():
225
+ """Load the language and embedding models once."""
226
  if STATE.get("model") is not None:
227
  return
228
 
 
258
  )
259
 
260
  initialize_memory()
261
+ logger.info("Reasoning engine initialized on %s with %d demonstrations", device, len(REASONING_EXAMPLES))
 
262
 
263
 
264
+ # =====================================================================
265
  # EXPERIENCE MEMORY
266
+ # =====================================================================
267
 
 
 
268
 
269
+ def initialize_memory():
 
 
 
270
  MEMORY_DB.parent.mkdir(parents=True, exist_ok=True)
 
271
  with sqlite3.connect(MEMORY_DB) as db:
272
  db.execute(
273
  """
 
291
  [text],
292
  normalize_embeddings=True,
293
  convert_to_numpy=True,
294
+ show_progress_bar=False,
295
  )[0]
296
 
297
 
298
+ def save_experience(query: str, plan: str, analysis: str, answer: str, quality: float = 1.0):
 
 
 
 
 
 
 
299
  try:
300
  with sqlite3.connect(MEMORY_DB) as db:
301
  db.execute(
 
304
  (query, plan, analysis, answer, quality, created)
305
  VALUES (?, ?, ?, ?, ?, ?)
306
  """,
307
+ (query, plan, analysis, answer, float(quality), time.time()),
 
 
 
 
 
 
 
308
  )
309
  db.commit()
310
  except Exception as exc:
 
312
 
313
 
314
  def retrieve_experiences(query: str, top_k: int = 3) -> List[Dict[str, Any]]:
 
315
  try:
316
  with sqlite3.connect(MEMORY_DB) as db:
317
  rows = db.execute(
 
329
 
330
  qv = _embed(query)
331
  scored = []
 
332
  for row in rows:
 
 
333
  rv = _embed(row[1])
334
+ scored.append((float(np.dot(qv, rv)), row))
 
 
335
  scored.sort(key=lambda x: x[0], reverse=True)
336
 
337
+ return [
338
+ {
339
+ "similarity": score,
340
+ "query": row[1],
341
+ "plan": row[2],
342
+ "analysis": row[3],
343
+ "answer": row[4],
344
+ "quality": row[5],
345
+ }
346
+ for score, row in scored[:top_k]
347
+ ]
 
 
 
 
348
  except Exception as exc:
349
  logger.warning("Experience retrieval failed: %s", exc)
350
  return []
351
 
352
 
353
+ # =====================================================================
354
+ # GENERATION + TRACE EXTRACTION
355
+ # =====================================================================
356
 
357
+
358
+ def generate(messages: List[Dict[str, str]], max_new_tokens: int = 1024, temperature: float = 0.15) -> str:
 
 
 
359
  """Run one model pass."""
360
  initialize_model()
361
 
362
  tokenizer = STATE["tokenizer"]
363
  model = STATE["model"]
364
 
365
+ prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
 
 
 
 
 
366
  inputs = tokenizer(prompt, return_tensors="pt")
367
+ inputs = {k: v.to(model.device) for k, v in inputs.items()}
368
+
369
+ generation_kwargs = {
370
+ "max_new_tokens": max_new_tokens,
371
+ "repetition_penalty": 1.05,
372
+ "pad_token_id": tokenizer.eos_token_id,
373
  }
374
+ if temperature > 0:
375
+ generation_kwargs.update({"temperature": temperature, "top_p": 0.90, "do_sample": True})
376
+ else:
377
+ generation_kwargs.update({"do_sample": False})
378
 
379
  with torch.no_grad():
380
+ output = model.generate(**inputs, **generation_kwargs)
 
 
 
 
 
 
 
 
381
 
382
  new_tokens = output[0][inputs["input_ids"].shape[1]:]
383
+ return tokenizer.decode(new_tokens, skip_special_tokens=True).strip()
384
+
385
 
386
+ def _extract_think(text: str) -> str:
387
+ """Extract the model's explicit <think> section if it emitted one."""
388
+ match = re.search(r"<think>\s*(.*?)\s*</think>", text, flags=re.IGNORECASE | re.DOTALL)
389
+ return match.group(1).strip() if match else ""
390
 
391
 
392
  def clean_think_block(text: str) -> str:
393
+ """Return a bounded visible reasoning trace plus the model output.
394
+
395
+ We intentionally expose a structured reasoning summary rather than
396
+ pretending that an arbitrary generated <think> block is a faithful dump
397
+ of private internal cognition.
398
+ """
399
  text = text.strip()
400
+ think = _extract_think(text)
401
+ body = re.sub(r"<think>.*?</think>", "", text, flags=re.IGNORECASE | re.DOTALL).strip()
402
+
403
+ if not body:
404
+ body = text.replace("<think>", "").replace("</think>", "").strip()
405
 
406
+ if SHOW_REASONING_TRACE and think:
407
+ return f"<think>\n{think}\n</think>\n\n{body}".strip()
408
+ return body
409
 
 
 
410
 
411
+ def _make_trace(stage: str, text: str) -> Dict[str, Any]:
412
+ """Create an inspectable stage trace from the explicit model output."""
413
+ think = _extract_think(text)
414
+ body = re.sub(r"<think>.*?</think>", "", text, flags=re.IGNORECASE | re.DOTALL).strip()
415
+ return {
416
+ "stage": stage,
417
+ "reasoning_summary": think,
418
+ "output": body,
419
+ }
420
 
421
 
422
+ # =====================================================================
423
  # COGNITIVE PASSES
424
+ # =====================================================================
425
 
426
  PLANNER_SYSTEM = r"""
427
  You are the planning component of Infinity GRM.
428
 
429
+ Produce a detailed but concise, inspectable reasoning trace. This is a
430
+ user-visible explanation of decisions, not a claim that it exposes private
431
+ hidden cognition.
432
 
433
  You must:
434
  - identify the actual task;
 
441
 
442
  Return:
443
  <think>
444
+ 1. Task interpretation
445
+ 2. Key assumptions/constraints
446
+ 3. Chosen method and why
447
+ 4. Subproblem decomposition
448
+ 5. Verification plan
449
  </think>
450
 
451
  Then return JSON with:
 
457
  "verification": ["..."],
458
  "difficulty": "easy|medium|hard|expert"
459
  }
 
 
460
  """
461
 
462
  ANALYST_SYSTEM = r"""
463
  You are the evidence-analysis component of Infinity GRM.
464
 
465
+ Give a detailed, inspectable reasoning summary. Do not merely restate the
466
+ answer. Explicitly identify evidence, assumptions, contradictions, missing
467
+ information, calculations, and verification checks.
468
+
469
+ Return:
470
+ <think>
471
+ 1. What the evidence establishes
472
+ 2. What it does not establish
473
+ 3. Important calculations/inferences
474
+ 4. Contradictions or uncertainty
475
+ 5. Verification result
476
+ </think>
477
+
478
+ Then provide the analyzed conclusion.
479
+ """
480
 
481
+ VERIFIER_SYSTEM = r"""
482
+ You are the verification component of Infinity GRM.
483
 
484
+ Audit the proposed analysis. Check correctness, unsupported claims,
485
+ calculations, edge cases, source consistency, and whether the conclusion
486
+ actually follows.
 
 
 
 
 
 
487
 
488
  Return:
489
  <think>
490
+ 1. Claim-by-claim checks
491
+ 2. Error/edge-case checks
492
+ 3. Independent sanity check
493
+ 4. Corrections required
494
+ 5. Final verification status
495
  </think>
496
 
497
+ Then provide a concise verification report.
498
  """
499
 
500
  FINAL_SYSTEM = r"""
501
+ You are the final synthesis component of Infinity GRM.
502
 
503
+ Answer the user directly using the plan, analysis, verification, and evidence.
504
+ Do not invent facts. If uncertainty remains, state it precisely.
 
 
 
 
 
 
 
 
 
 
 
 
505
 
506
+ Return:
507
  <think>
508
+ 1. What was established
509
+ 2. How the verification affected the result
510
+ 3. What answer follows
511
+ 4. Any material caveat
512
  </think>
513
 
514
+ Then give the final answer in a useful format.
 
 
 
515
  """
516
 
517
 
518
  def plan(query: str, history: List[Dict[str, str]]) -> Dict[str, Any]:
 
519
  experiences = retrieve_experiences(query, top_k=3)
520
+ experience_text = json.dumps(experiences, ensure_ascii=False, indent=2)
 
 
 
 
 
 
 
521
 
522
  messages = [
523
  {"role": "system", "content": PLANNER_SYSTEM},
524
  {
525
  "role": "user",
526
  "content": (
527
+ f"QUESTION:\n{query}\n\n"
528
+ f"HISTORY:\n{json.dumps(history[-6:], ensure_ascii=False)}\n\n"
529
+ f"PRIOR EXPERIENCES:\n{experience_text}\n\n"
530
  f"RELEVANT REASONING DEMONSTRATIONS:\n{_format_reasoning_examples(query, top_k=8)}"
531
  ),
532
  },
533
  ]
534
 
535
+ raw = generate(messages, max_new_tokens=1400, temperature=0.10)
536
+ think = _extract_think(raw)
537
+ json_match = re.search(r"\{.*\}", raw, flags=re.DOTALL)
 
 
 
 
 
 
 
 
538
 
539
  if json_match:
540
  try:
 
546
  pass
547
 
548
  return {
549
+ "think": think,
550
+ "task": query,
551
  "requires_web": False,
552
  "search_queries": [],
553
+ "steps": ["Clarify the task", "Solve using the most appropriate method", "Verify the result"],
554
+ "verification": ["Check assumptions and edge cases"],
555
  "difficulty": "hard",
556
  "experiences": experiences,
557
  }
558
 
559
 
560
+ def analyze(query: str, plan_data: Dict[str, Any], evidence: str, history: List[Dict[str, str]]) -> str:
 
 
 
 
 
 
561
  messages = [
562
  {"role": "system", "content": ANALYST_SYSTEM},
563
  {
 
571
  ),
572
  },
573
  ]
574
+ return generate(messages, max_new_tokens=1600, temperature=0.10)
575
 
576
+
577
+ def verify(query: str, plan_data: Dict[str, Any], analysis: str, evidence: str) -> str:
578
+ """Independent verification pass."""
579
+ messages = [
580
+ {"role": "system", "content": VERIFIER_SYSTEM},
581
+ {
582
+ "role": "user",
583
+ "content": (
584
+ f"QUESTION:\n{query}\n\n"
585
+ f"PLAN:\n{json.dumps(plan_data, indent=2)}\n\n"
586
+ f"ANALYSIS:\n{analysis[:18000]}\n\n"
587
+ f"EVIDENCE:\n{evidence[:20000]}"
588
+ ),
589
+ },
590
+ ]
591
+ return generate(messages, max_new_tokens=1400, temperature=0.05)
592
 
593
 
594
  def final_answer(
 
597
  analysis: str,
598
  evidence: str,
599
  history: List[Dict[str, str]],
600
+ verification: Optional[str] = None,
601
  ) -> str:
602
+ """Final reasoning/synthesis pass.
603
+
604
+ `verification` is optional to preserve compatibility with the previous
605
+ five-argument search pipeline.
606
+ """
607
+ verification_text = verification or "No separate verification pass was supplied."
608
  messages = [
609
  {"role": "system", "content": FINAL_SYSTEM},
610
  {
 
612
  "content": (
613
  f"QUESTION:\n{query}\n\n"
614
  f"PLAN:\n{json.dumps(plan_data, indent=2)}\n\n"
615
+ f"ANALYSIS:\n{analysis[:18000]}\n\n"
616
+ f"VERIFICATION:\n{verification_text[:16000]}\n\n"
617
  f"EVIDENCE:\n{evidence[:20000]}\n\n"
618
+ f"HISTORY:\n{json.dumps(history[-8:], ensure_ascii=False)}\n\n"
619
+ f"RELEVANT REASONING DEMONSTRATIONS:\n{_format_reasoning_examples(query, top_k=6)}"
620
  ),
621
  },
622
  ]
623
+ return generate(messages, max_new_tokens=2200, temperature=0.10)
624
 
625
+
626
+ def build_reasoning_trace(
627
+ query: str,
628
+ plan_data: Dict[str, Any],
629
+ analysis: str,
630
+ verification: str,
631
+ final: str,
632
+ ) -> Dict[str, Any]:
633
+ """Return a detailed visible trace of the reasoning pipeline."""
634
+ return {
635
+ "query": query,
636
+ "demonstration_count": len(REASONING_EXAMPLES),
637
+ "stages": [
638
+ {
639
+ "stage": "planning",
640
+ "reasoning_summary": plan_data.get("think", ""),
641
+ "structured_plan": plan_data,
642
+ },
643
+ _make_trace("analysis", analysis),
644
+ _make_trace("verification", verification),
645
+ _make_trace("final_synthesis", final),
646
+ ],
647
+ }
648
 
649
 
650
  def learn_from_result(
 
654
  answer: str,
655
  quality: float = 1.0,
656
  ):
 
657
  save_experience(
658
  query=query,
659
  plan=json.dumps(plan_data, ensure_ascii=False),
 
667
  initialize_model()
668
 
669
 
 
 
670
  if __name__ == "__main__":
671
  initialize()
672
+ print("Infinity GRM reasoning engine initialized.")
673
+ print(f"Structured reasoning demonstrations: {len(REASONING_EXAMPLES)}")