"""Apply the engine-3.0 integration edits to a checkout of the UniHive `main` repo (python apply_main_patch.py ). 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")])