From 3606a4f112aaa85ec15ddc4a263200fba43671a5 Mon Sep 17 00:00:00 2001 From: eezd Date: Mon, 2 Nov 2026 19:17:14 +0800 Subject: [PATCH] fix(news): compact large synthesis inputs by package --- backend/src/alphapulse/news_risk/briefing.py | 4 +++- backend/tests/test_news_tuning.py | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/backend/src/alphapulse/news_risk/briefing.py b/backend/src/alphapulse/news_risk/briefing.py index 66f3b7d..715c32c 100644 --- a/backend/src/alphapulse/news_risk/briefing.py +++ b/backend/src/alphapulse/news_risk/briefing.py @@ -65,7 +65,9 @@ async def generate(provider, system, inputs, ranking_only=False, rankings=None): pending = list(inputs) if rankings is None else [] if rankings is not None: reading = rankings - notes = [json.dumps({'packages': inputs, 'ranking': rankings}, ensure_ascii=False, default=str)] + by_id = {(r.get('kind', 'package'), r['id'], r['revision']): r for r in rankings} + notes = [json.dumps({'package': p, 'ranking': by_id[(p.get('kind', 'package'), p['id'], p['revision'])]}, + ensure_ascii=False, default=str) for p in inputs] while pending: batch = [] while pending and fits_context(provider, system, {'task': 'ranking', 'packages': [*batch, pending[0]]}, Ranked): diff --git a/backend/tests/test_news_tuning.py b/backend/tests/test_news_tuning.py index ed4ebd6..bc84a77 100644 --- a/backend/tests/test_news_tuning.py +++ b/backend/tests/test_news_tuning.py @@ -116,3 +116,21 @@ def test_ranking_only_skips_synthesis_and_synthesis_reuses_priority(trading,monk result=asyncio.run(briefing.generate(provider,'rules',inputs,rankings=ranked['reading'])) assert calls==['ranking','synthesis'] assert result['synthesis']['references']==ranked['reading'] + + +def test_large_synthesis_compacts_package_notes_in_batches(trading,monkeypatch): + import json + from alphapulse.news_risk import briefing + inputs=[{'id':i,'revision':1,'importance_stars':3,'result':{'summary':'x'*800}} for i in range(3)] + rankings=[{'kind':'package','id':i,'revision':1,'priority':50,'reason':'Read'} for i in range(3)] + calls=[] + def fits(provider,system,payload,schema): return len(json.dumps(payload)) < 1600 + async def complete(provider,system,payload,schema): + calls.append(payload['task']) + if schema is briefing.Notes: return schema(notes='Compacted'),{} + trend={'summary':'Unknown','conditions':'Unknown','counter_evidence':'Unknown','watchpoints':'Unknown'} + return schema(summary='Synthetic',market='Unknown',short_term=trend,medium_term=trend,references=[]),{} + monkeypatch.setattr(briefing,'fits_context',fits);monkeypatch.setattr(briefing,'complete',complete) + result=asyncio.run(briefing.generate(N(),'rules',inputs,rankings=rankings)) + assert calls==['synthesis_notes']*3+['synthesis'] + assert len(result['reading'])==3