107 lines
4.3 KiB
Python
107 lines
4.3 KiB
Python
"""HEL-882 add-on to the manager's SDK review: the re-enqueued mem0 batch is
|
|
actually processed (tick) and becomes searchable — completing the stub→mem0
|
|
recovery proof (the review script stops after enqueue_count). Same boundary:
|
|
deterministic 512-dim embedding installed before TextEmbedding construction,
|
|
socket rejects non-loopback, temp ledger/vector dirs only, zero real LLM
|
|
(fake 127.0.0.1 gateway), zero real embeddings, zero downloads."""
|
|
import asyncio
|
|
import hashlib
|
|
import importlib.util
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import socket
|
|
import sys
|
|
import tempfile
|
|
|
|
ROOT = Path('/home/xiaomo/multica_workspaces/hello-af23464d222e/hel-882-f72ebe62dddc/workdir')
|
|
REPO = ROOT / 'CyberGril'
|
|
sys.path.insert(0, str(REPO / 'src'))
|
|
for name in ('OPENROUTER_API_KEY', 'OPENAI_API_KEY', 'OPENAI_BASE_URL'):
|
|
os.environ.pop(name, None)
|
|
spec = importlib.util.spec_from_file_location('contract', REPO / 'tools/verify_mem0_real_hel874.py')
|
|
contract = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(contract)
|
|
|
|
real_connect = socket.socket.connect
|
|
|
|
|
|
def connect(sock, addr):
|
|
if isinstance(addr, tuple) and addr[0] not in ('127.0.0.1', '::1', 'localhost'):
|
|
raise AssertionError('addon forbids non-loopback connection')
|
|
return real_connect(sock, addr)
|
|
|
|
|
|
socket.socket.connect = connect
|
|
|
|
import numpy as np
|
|
import mem0.embeddings.fastembed as embedding_module
|
|
|
|
|
|
class DeterministicEmbedding:
|
|
embedding_size = 512
|
|
calls = 0
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
pass
|
|
|
|
def embed(self, texts, *args, **kwargs):
|
|
for text in ([texts] if isinstance(texts, str) else texts):
|
|
type(self).calls += 1
|
|
digest = hashlib.sha256(text.encode()).digest()
|
|
yield np.array([digest[i % 32] / 255.0 for i in range(512)], dtype=np.float32)
|
|
|
|
|
|
embedding_module.TextEmbedding = DeterministicEmbedding
|
|
|
|
from cybergril.memory.semantic import Mem0Backend, SemanticMemory, StubBackend
|
|
from cybergril.memory.store import Store
|
|
|
|
|
|
async def main():
|
|
full = os.popen(f'git -C {REPO} rev-parse HEAD').read().strip()
|
|
result = {'head': full, 'real_llm_requests': 0, 'real_embeddings': 0,
|
|
'embedding_boundary': 'deterministic 512-dim; no model loaded',
|
|
'external_network': 'socket.connect rejects non-loopback'}
|
|
with tempfile.TemporaryDirectory(prefix='hel882-addon-', dir=ROOT) as td:
|
|
tmp = Path(td)
|
|
server = contract.start_gateway()
|
|
try:
|
|
store = Store(tmp / 'switch.db')
|
|
with store.conn:
|
|
store.execute("INSERT INTO chat_message(ts,role,text,turn_id,status) "
|
|
"VALUES(1,'user','另一条合成原话','t2','sent')")
|
|
stub = SemanticMemory(store, StubBackend())
|
|
stub.enqueue_uncovered()
|
|
await stub.tick()
|
|
ledger = tmp / 'switch.sqlite3'
|
|
contract.make_ledger(ledger, 50, 5)
|
|
cfg = contract.config_for(tmp / 'switch', ledger, port=server.server_address[1],
|
|
cap=50, llm_cap=5)
|
|
backend = Mem0Backend(cfg)
|
|
live = SemanticMemory(store, backend)
|
|
result['stub_batch'] = dict(store.query_one("SELECT backend,state FROM sem_batch"
|
|
" WHERE backend='stub'"))
|
|
result['mem0_enqueue_count'] = live.enqueue_uncovered()
|
|
await live.tick()
|
|
batch = dict(store.query_one("SELECT state,reason,entry_ids FROM sem_batch"
|
|
" WHERE backend='mem0'"))
|
|
result['mem0_batch_after_tick'] = batch
|
|
result['mem0_hits'] = await backend.search('另一条合成原话')
|
|
result['mem0_reenqueue_after_done'] = live.enqueue_uncovered()
|
|
result['embed_ledger_used'] = backend.ledger.used()
|
|
result['llm_ledger_used'] = backend.llm_guard.used()
|
|
backend._memory.llm.client.close()
|
|
await backend.aclose()
|
|
store.close()
|
|
finally:
|
|
server.shutdown()
|
|
server.server_close()
|
|
result['deterministic_vector_items'] = DeterministicEmbedding.calls
|
|
out = ROOT / 'HEL-882-sdk-addon-stub-switch.json'
|
|
out.write_text(json.dumps(result, ensure_ascii=False, indent=2))
|
|
print(json.dumps(result, ensure_ascii=False, indent=2))
|
|
|
|
|
|
asyncio.run(main())
|