File size: 4,947 Bytes
6b1bc4b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | """Apply the engine-3.0 integration edits to a checkout of the UniHive `main` repo (python apply_main_patch.py <repo root>).
Every replacement must match exactly once, so the script refuses to run on a different version of the files.
backend/personalization/service.py : create_slate asks the hybrid engine for POST scores when PERSONALIZATION_ENGINE=hybrid (falls back to the baseline on any error)
backend/tagging.py : default tagger model gpt-oss-120b (with the token budget a reasoning model needs)
backend/requirements.txt : onnxruntime stated explicitly (fastembed already pulls it in)
docker-compose.yml : mounts migration 012 for fresh databases"""
import os, sys
root = sys.argv[1]
def patch(rel, pairs):
p = os.path.join(root, rel); s = open(p, encoding="utf8", newline="").read(); crlf = "\r\n" in s; s = s.replace("\r\n", "\n")
for old, new in pairs:
assert s.count(old) == 1, f"{rel}: expected exactly one match for: {old[:90]!r} (found {s.count(old)})"
s = s.replace(old, new)
open(p, "w", encoding="utf8", newline="").write(s.replace("\n", "\r\n") if crlf else s); print("patched", rel)
patch("backend/personalization/service.py", [
("from .math import features, aggregate, affinities, reading_reward, rank_score, diversify, MODEL_VERSION, decay\n",
"from .math import features, aggregate, affinities, reading_reward, rank_score, diversify, MODEL_VERSION, decay\n"
"import logging\nfrom . import hybrid as hybrid_engine\n\n_log=logging.getLogger('personalization')\nHYBRID_SUFFIX='+hybrid-3.0-bge384'\n\n"
"def _model_version(items):\n \"\"\"The snapshot's model version: the baseline's, plus a suffix when the hybrid engine scored any post in it.\"\"\"\n"
" return MODEL_VERSION+HYBRID_SUFFIX if any((i.get('features') or {}).get('engine') for i in items) else MODEL_VERSION\n"),
(" ranked=[]\n for entity_type,entities in [('POST',posts),('PROJECT',projects)]:\n",
" hybrid=None\n if state['enabled'] and posts and hybrid_engine.enabled():\n"
" # Engine 3.0 scores the POSTS (projects keep the baseline); any failure falls back to the baseline ranker for this slate.\n"
" try:\n from .hybrid.main_adapter import score_posts_for_slate\n"
" hybrid=await score_posts_for_slate(c,hybrid_engine.get_engine(),user_id,posts,[dict(v) for v in vectors],order_mode=hybrid_engine.order_mode())\n"
" except Exception:\n _log.exception('Hybrid engine failed; using the baseline ranker for this slate');hybrid=None\n"
" ranked=[]\n for entity_type,entities in [('POST',posts),('PROJECT',projects)]:\n"),
(" score,reasons,values=rank_score(entity,f,state['preferences'],state['declared'],skill_match=skill_match,semantic=semantic)\n",
" if entity_type=='POST' and hybrid is not None and str(entity['id']) in hybrid:\n"
" h=hybrid[str(entity['id'])];score,reasons,values=h['score'],h['reasons'],{**h['features'],'engine':'hybrid-3.0-bge384','engine_score':h['engine_score']}\n"
" else:score,reasons,values=rank_score(entity,f,state['preferences'],state['declared'],skill_match=skill_match,semantic=semantic)\n"),
("('news' if news else 'home'),state['version'],MODEL_VERSION,items)\n", "('news' if news else 'home'),state['version'],_model_version(items),items)\n"),
("'reasons':item['reasons'],'model_version':MODEL_VERSION}\n", "'reasons':item['reasons'],'model_version':_model_version(items)}\n"),
("'request_id':str(request_id),'model_version':MODEL_VERSION}\n", "'request_id':str(request_id),'model_version':_model_version(items)}\n"),
])
patch("backend/tagging.py", [
("def provider_tags(title, content, domains):\n",
"def _model():\n return os.getenv('TAGGING_MODEL', 'openai/gpt-oss-120b')\n\n"
"def _extra():\n # A reasoning model spends completion tokens on reasoning: give it room and keep the reasoning short.\n"
" return {'reasoning_effort':'low','max_tokens':1500} if _model().startswith('openai/gpt-oss') else {'max_tokens':250}\n\n"
"def provider_tags(title, content, domains):\n"),
("json={'model':os.getenv('TAGGING_MODEL','llama-3.3-70b-versatile'),", "json={'model':_model(),"),
("'temperature':0,'max_tokens':250})", "'temperature':0,**_extra()})"),
])
patch("backend/requirements.txt", [("fastembed==0.7.4", "fastembed==0.7.4\nonnxruntime>=1.18")])
patch("docker-compose.yml", [(" - ./backend/migrations/011_social_moderation.sql:/docker-entrypoint-initdb.d/11_social_moderation.sql:ro\n",
" - ./backend/migrations/011_social_moderation.sql:/docker-entrypoint-initdb.d/11_social_moderation.sql:ro\n"
" - ./backend/migrations/012_domains_catalogue.sql:/docker-entrypoint-initdb.d/12_domains_catalogue.sql:ro\n")])
|