RFTSystems commited on
Commit
91bebbd
·
verified ·
1 Parent(s): bc6a96c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -48
app.py CHANGED
@@ -96,7 +96,6 @@ class RFTMemoryStore:
96
  )
97
  """)
98
 
99
- # FTS index
100
  cur.execute("""
101
  CREATE VIRTUAL TABLE IF NOT EXISTS events_fts USING fts5(
102
  event_id,
@@ -133,6 +132,34 @@ class RFTMemoryStore:
133
  os.makedirs(d, exist_ok=True)
134
  return d
135
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  def collapse_score(self, session_id: str, role: str, text: str) -> float:
137
  role_w = {"user": 1.0, "tool": 0.9, "assistant": 0.6}.get(role, 0.7)
138
  tokens = set(t.lower() for t in re.findall(r"[A-Za-z0-9_]+", text or ""))
@@ -206,7 +233,7 @@ class RFTMemoryStore:
206
  f.flush()
207
  os.fsync(f.fileno())
208
 
209
- # Update indexes
210
  con = sqlite3.connect(self.db_path)
211
  cur = con.cursor()
212
  cur.execute("""
@@ -219,34 +246,6 @@ class RFTMemoryStore:
219
 
220
  return rec
221
 
222
- def get_events(self, session_id: str, limit: int = 400) -> List[Dict[str, Any]]:
223
- con = sqlite3.connect(self.db_path)
224
- cur = con.cursor()
225
- cur.execute("""
226
- SELECT event_id, seq, ts_ms, role, text, digest, prev_hash, chain_hash, collapse
227
- FROM events
228
- WHERE session_id=?
229
- ORDER BY seq ASC
230
- LIMIT ?
231
- """, (session_id, int(limit)))
232
- rows = cur.fetchall()
233
- con.close()
234
-
235
- out = []
236
- for r in rows:
237
- out.append({
238
- "event_id": r[0],
239
- "seq": int(r[1] or 0),
240
- "ts_ms": r[2],
241
- "role": r[3],
242
- "text": r[4],
243
- "digest": r[5],
244
- "prev_hash": r[6],
245
- "chain_hash": r[7],
246
- "collapse": float(r[8] or 0.0),
247
- })
248
- return out
249
-
250
  def search_lexical(self, session_id: str, query: str, k: int = 8) -> List[RetrievalHit]:
251
  match = safe_fts_match(query)
252
 
@@ -284,7 +283,7 @@ class RFTMemoryStore:
284
  "event_id": h.event_id,
285
  "seq": h.seq,
286
  "role": h.role,
287
- "text": h.text,
288
  "score": h.score,
289
  "digest": h.digest,
290
  "chain_hash": h.chain_hash
@@ -360,8 +359,8 @@ GUIDED_DEMO_STEPS = [
360
  "What city did I say?",
361
  "My favourite drink is Coke Zero now. This overrides earlier.",
362
  "What’s my favourite drink?",
363
- "Search for 'Nova' and show the matching memory line.",
364
- "Search for 'Coke' and show the matching memory line.",
365
  ]
366
 
367
  HOW_TO_MD = """
@@ -396,6 +395,7 @@ def new_session_id() -> str:
396
 
397
 
398
  def events_to_messages(events: List[Dict[str, Any]]) -> List[Dict[str, str]]:
 
399
  msgs = []
400
  for e in events:
401
  if e["role"] in ("user", "assistant"):
@@ -455,20 +455,19 @@ def chat_turn(session_id: str, user_msg: str, retrieval_k: int):
455
  retrieved_view = "\n".join([f"{h.score:.4f} | {h.role} | {h.text}" for h in hits]) if hits else "(none)"
456
  messages = events_to_messages(events)
457
 
458
- return session_id, messages, retrieved_view, ledger, receipt_path
 
459
 
460
 
461
  def run_guided_demo(session_id: str, retrieval_k: int):
462
  if not session_id:
463
  session_id = new_session_id()
464
 
465
- last_receipt = ""
466
- last_retrieved = ""
467
- last_ledger = ""
468
  for step in GUIDED_DEMO_STEPS:
469
- session_id, messages, last_retrieved, last_ledger, last_receipt = chat_turn(session_id, step, retrieval_k)
470
-
471
- return session_id, messages, last_retrieved, last_ledger, last_receipt
472
 
473
 
474
  def manual_search(session_id: str, query: str, k: int) -> str:
@@ -501,7 +500,7 @@ def verify_uploaded_receipt(file_obj) -> str:
501
 
502
  def reset_session():
503
  sid = new_session_id()
504
- return sid, [], "", "", None
505
 
506
 
507
  def fill_example(selected: str) -> str:
@@ -519,7 +518,8 @@ with gr.Blocks(title="RFT Memory Receipt Engine") as demo:
519
 
520
  with gr.Tabs():
521
  with gr.Tab("Chat"):
522
- chatbot = gr.Chatbot(label="Conversation", height=320, type="messages")
 
523
 
524
  with gr.Row():
525
  example_pick = gr.Dropdown(label="Example prompts", choices=EXAMPLE_PROMPTS, value=EXAMPLE_PROMPTS[0])
@@ -539,14 +539,14 @@ with gr.Blocks(title="RFT Memory Receipt Engine") as demo:
539
  send.click(
540
  chat_turn,
541
  inputs=[session_id, user_msg, retrieval_k],
542
- outputs=[session_id, chatbot, retrieved_out, ledger_out, receipt_path],
543
- ).then(lambda p: p, inputs=[receipt_path], outputs=[receipt_file])
544
 
545
  with gr.Tab("Guided Demo"):
546
  gr.Markdown("Runs a scripted set of messages to show storage, recall, overrides, search, and receipts.")
547
  run_demo_btn = gr.Button("Run Guided Demo", variant="primary")
548
 
549
- demo_chatbot = gr.Chatbot(label="Demo conversation", height=320, type="messages")
550
  demo_retrieved = gr.Textbox(label="Last retrieved memory slices", lines=8)
551
  demo_ledger = gr.Textbox(label="Ledger after demo", lines=14)
552
  demo_receipt_path = gr.Textbox(label="Last demo receipt path (server)", lines=1)
@@ -555,8 +555,8 @@ with gr.Blocks(title="RFT Memory Receipt Engine") as demo:
555
  run_demo_btn.click(
556
  run_guided_demo,
557
  inputs=[session_id, retrieval_k],
558
- outputs=[session_id, demo_chatbot, demo_retrieved, demo_ledger, demo_receipt_path],
559
- ).then(lambda p: p, inputs=[demo_receipt_path], outputs=[demo_receipt_file])
560
 
561
  with gr.Tab("Manual Search"):
562
  q = gr.Textbox(label="Search query", placeholder="Type keywords…")
@@ -576,7 +576,7 @@ with gr.Blocks(title="RFT Memory Receipt Engine") as demo:
576
  new_sess_btn.click(
577
  reset_session,
578
  inputs=[],
579
- outputs=[session_id, chatbot, retrieved_out, ledger_out, receipt_file],
580
  )
581
 
582
  demo.launch()
 
96
  )
97
  """)
98
 
 
99
  cur.execute("""
100
  CREATE VIRTUAL TABLE IF NOT EXISTS events_fts USING fts5(
101
  event_id,
 
132
  os.makedirs(d, exist_ok=True)
133
  return d
134
 
135
+ def get_events(self, session_id: str, limit: int = 400) -> List[Dict[str, Any]]:
136
+ con = sqlite3.connect(self.db_path)
137
+ cur = con.cursor()
138
+ cur.execute("""
139
+ SELECT event_id, seq, ts_ms, role, text, digest, prev_hash, chain_hash, collapse
140
+ FROM events
141
+ WHERE session_id=?
142
+ ORDER BY seq ASC
143
+ LIMIT ?
144
+ """, (session_id, int(limit)))
145
+ rows = cur.fetchall()
146
+ con.close()
147
+
148
+ out = []
149
+ for r in rows:
150
+ out.append({
151
+ "event_id": r[0],
152
+ "seq": int(r[1] or 0),
153
+ "ts_ms": r[2],
154
+ "role": r[3],
155
+ "text": r[4],
156
+ "digest": r[5],
157
+ "prev_hash": r[6],
158
+ "chain_hash": r[7],
159
+ "collapse": float(r[8] or 0.0),
160
+ })
161
+ return out
162
+
163
  def collapse_score(self, session_id: str, role: str, text: str) -> float:
164
  role_w = {"user": 1.0, "tool": 0.9, "assistant": 0.6}.get(role, 0.7)
165
  tokens = set(t.lower() for t in re.findall(r"[A-Za-z0-9_]+", text or ""))
 
233
  f.flush()
234
  os.fsync(f.fileno())
235
 
236
+ # Index update
237
  con = sqlite3.connect(self.db_path)
238
  cur = con.cursor()
239
  cur.execute("""
 
246
 
247
  return rec
248
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  def search_lexical(self, session_id: str, query: str, k: int = 8) -> List[RetrievalHit]:
250
  match = safe_fts_match(query)
251
 
 
283
  "event_id": h.event_id,
284
  "seq": h.seq,
285
  "role": h.role,
286
+ "content": h.text,
287
  "score": h.score,
288
  "digest": h.digest,
289
  "chain_hash": h.chain_hash
 
359
  "What city did I say?",
360
  "My favourite drink is Coke Zero now. This overrides earlier.",
361
  "What’s my favourite drink?",
362
+ "Search for Nova and show the matching memory line.",
363
+ "Search for Coke and show the matching memory line.",
364
  ]
365
 
366
  HOW_TO_MD = """
 
395
 
396
 
397
  def events_to_messages(events: List[Dict[str, Any]]) -> List[Dict[str, str]]:
398
+ # Gradio expects: [{"role": "...", "content": "..."}, ...]
399
  msgs = []
400
  for e in events:
401
  if e["role"] in ("user", "assistant"):
 
455
  retrieved_view = "\n".join([f"{h.score:.4f} | {h.role} | {h.text}" for h in hits]) if hits else "(none)"
456
  messages = events_to_messages(events)
457
 
458
+ # IMPORTANT: return receipt_path twice so File can download it
459
+ return session_id, messages, retrieved_view, ledger, receipt_path, receipt_path
460
 
461
 
462
  def run_guided_demo(session_id: str, retrieval_k: int):
463
  if not session_id:
464
  session_id = new_session_id()
465
 
466
+ last = (session_id, [], "", "", "", None)
 
 
467
  for step in GUIDED_DEMO_STEPS:
468
+ last = chat_turn(session_id, step, retrieval_k)
469
+ session_id = last[0]
470
+ return last
471
 
472
 
473
  def manual_search(session_id: str, query: str, k: int) -> str:
 
500
 
501
  def reset_session():
502
  sid = new_session_id()
503
+ return sid, [], "", "", "", None
504
 
505
 
506
  def fill_example(selected: str) -> str:
 
518
 
519
  with gr.Tabs():
520
  with gr.Tab("Chat"):
521
+ # DO NOT pass type=... (your Gradio doesn't accept it)
522
+ chatbot = gr.Chatbot(label="Conversation", height=320)
523
 
524
  with gr.Row():
525
  example_pick = gr.Dropdown(label="Example prompts", choices=EXAMPLE_PROMPTS, value=EXAMPLE_PROMPTS[0])
 
539
  send.click(
540
  chat_turn,
541
  inputs=[session_id, user_msg, retrieval_k],
542
+ outputs=[session_id, chatbot, retrieved_out, ledger_out, receipt_path, receipt_file],
543
+ )
544
 
545
  with gr.Tab("Guided Demo"):
546
  gr.Markdown("Runs a scripted set of messages to show storage, recall, overrides, search, and receipts.")
547
  run_demo_btn = gr.Button("Run Guided Demo", variant="primary")
548
 
549
+ demo_chatbot = gr.Chatbot(label="Demo conversation", height=320)
550
  demo_retrieved = gr.Textbox(label="Last retrieved memory slices", lines=8)
551
  demo_ledger = gr.Textbox(label="Ledger after demo", lines=14)
552
  demo_receipt_path = gr.Textbox(label="Last demo receipt path (server)", lines=1)
 
555
  run_demo_btn.click(
556
  run_guided_demo,
557
  inputs=[session_id, retrieval_k],
558
+ outputs=[session_id, demo_chatbot, demo_retrieved, demo_ledger, demo_receipt_path, demo_receipt_file],
559
+ )
560
 
561
  with gr.Tab("Manual Search"):
562
  q = gr.Textbox(label="Search query", placeholder="Type keywords…")
 
576
  new_sess_btn.click(
577
  reset_session,
578
  inputs=[],
579
+ outputs=[session_id, chatbot, retrieved_out, ledger_out, receipt_path, receipt_file],
580
  )
581
 
582
  demo.launch()