
    E1j6                       d Z ddlmZ ddlZej
                  j                  dd       ddlmZ	  e	d      Z
ddlmZ ddlmZ ddlZddlZddlZddlZddlZddlZdd	lmZmZ dd
lmZ  ed      ZdZddZddZd dZ	 	 	 	 	 	 	 	 d!dZd"d#dZd$dZ d%d&dZ!d'dZ"d(d)dZ#d*d+dZ$d,dZ%d-dZ&d.d/dZ'd0dZ(e)dk(  r7e
jU                  d        ejV                   e(ejX                  dd              yy)1u  
Aria Knowledge Pipeline (AKP) — Stage 2: Triage
KAR-74 · 2026-05-12

Liest alle ingested Videos ohne triaged-Eintrag, schickt Transcript-Excerpt an
Haiku 4.5 mit JSON-Rubric (depth/novelty/aria_relevance/production_ready 0-3),
schreibt Verdict (promote/summary_only/skip) nach triage/<video-id>.json,
trackt Cost gegen Daily-Cap.

Gated auf ANTHROPIC_API_KEY — fehlt der, wird sauber gequeued (kein Crash).
    )annotationsNz/root/aria/lib)
get_loggeraria-akp-triage)audit)trace_llm_call)datetimetimezone)Pathz%/root/aria/brain/youtube/.config.yamlu  Du bist Arias Triage-Filter fuer Wissens-Videos.

Bewerte das Video auf 4 Qualitaets-Achsen PLUS 1 Junk-Penalty-Achse, Skala 0-3.

Qualitaets-Achsen (0=schwach, 1=mittelmaessig, 2=gut, 3=stark):
1. depth: Tiefe der Insights vs. Oberflaeche (Skript-Tiefe, Argumentations-Schritte)
2. novelty: Neuigkeit vs. wiedergekaute Best-Practices (Datum/Stand-Bezug, neue Konzepte)
3. aria_relevance: Relevanz fuer Aria-Ziele (Multi-Agent-Patterns, Eval-Setup, Memory-Design, LLM-Distribution, Engineering-Principles, Brain-Architektur, Observability, Cost-Optimierung)
4. production_ready: Direkt umsetzbar vs. theoretisch (Code/Workflow/Architektur in der Praxis nutzbar)

Junk-Penalty-Achse (LLM-Brain-Rot-Guard, Xing et al. 2025 / arXiv:2510.13928 —
Junk-Content verursacht nachweislich dauerhaften Capability-Decay):
5. junk_penalty: Wie stark zeigt der Content schaedliche Junk-Marker?
   0 = sauber, faktenbasiert, ausargumentiert
   1 = leichte Hype-Tendenz, aber Substanz ueberwiegt
   2 = deutlicher Clickbait/Engagement-Bait ODER Thought-Skipping (Ergebnis-Behauptung ohne Reasoning-Schritte)
   3 = reiner Sensationalismus/Hype ohne Substanz, uebertriebene/unbelegte Claims, Meinung als Fakt
   Junk-Marker: "WOW"/"SHOCKING"/"you won't believe", Hype ohne Beleg, fehlende Reasoning-Kette.
   WICHTIG: Viralitaet/Kuerze ist KEIN Wert-Signal. Substanz schlaegt Reichweite.

Verdict wird deterministisch aus den Scores berechnet (du musst es nicht selbst bestimmen),
aber setze "verdict": "skip" wenn der Content komplett wertlos ist.
Die Junk-Penalty zieht den effektiven Score runter; junk_penalty=3 erzwingt skip,
junk_penalty>=2 verhindert promote.

Output AUSSCHLIESSLICH ein JSON-Objekt mit dieser Struktur (keine Erklaerung drumherum):
{{"depth": int, "novelty": int, "aria_relevance": int, "production_ready": int, "junk_penalty": int, "verdict": "promote"|"summary_only"|"skip", "one_line_reason": str}}

Video:
- Titel: {title}
- Channel: {channel}
- Dauer: {duration_min} min
- Upload: {upload_date}

Transcript-Excerpt:
{transcript_excerpt}
c                     t         j                         5 } t        j                  |       cd d d        S # 1 sw Y   y xY wN)CONFIG_PATHopenyaml	safe_load)fs    %/root/aria/scripts/aria-akp-triage.pyload_configr   B   s1    				 !q~~a ! ! !s   4=c                Z    t        j                  |       }t         j                  |_        |S r   )sqlite3connectRowrow_factory)db_pathcons     r   db_connr   G   s     
//'
"CkkCOJ    c                    | j                  d      D ch c]  }|d   	 }}d|vr"| j                  d       | j                          yyc c}w )zFIdempotente Migration: junk_penalty-Spalte (KAR-685, Brain-Rot-Guard).zPRAGMA table_info(triaged)   junk_penaltyz=ALTER TABLE triaged ADD COLUMN junk_penalty INTEGER DEFAULT 0Nexecutecommit)r   rcolss      r   ensure_schemar%   M   sL    ++&BCDQAaDDDDT!ST

 " Es   A	c           	     
   t        dt        dt        |                  }| d   | d   z   | d   z   | d   z   dz  }t        d|d	|z  z
        }|dk\  rd
}n,||k\  r| d   |k\  r|dk  rd}n||k\  s| d   |k\  r|dk  rd}nd
}|||fS )al  Pure verdict-Logik (testbar, ohne API). Junk-Penalty zieht effektiven Score runter.

    Returns: (verdict, avg_positive, effective_avg)
    Regeln (KAR-685):
      - junk_penalty=3        -> immer skip (reiner Junk, Brain-Rot-Risiko)
      - junk_penalty>=2        -> nie promote (max summary_only)
      - effective = max(0, avg_positive - 0.5*junk_penalty)
    r      depthnoveltyaria_relevanceproduction_ready      @        g      ?skip   promotesummary_only)maxminint)	scoresr   promote_avgpromote_ariasummary_avgjpavg_positiveeffverdicts	            r   compute_verdictr=   U   s     
QAs<()	*B7OfY&77-./178J1KLORSL
c<#(*
+C	Qw		'7 8L HRRSV		'7 8L HRRSV L#%%r   c                :    t        | j                  d|f            S )Na  SELECT i.video_id, i.channel, i.title, i.duration_seconds, i.url,
                   i.published_at AS upload_date, i.raw_path
            FROM ingested i
            LEFT JOIN triaged t ON t.video_id = i.video_id
            WHERE i.skipped_reason IS NULL
              AND i.raw_path IS NOT NULL
              AND t.video_id IS NULL
            ORDER BY i.ingested_at ASC
            LIMIT ?)listr!   )r   limits     r   get_pendingrA   o   s&    	 
  r   c                    t        j                  t        j                        j	                         j                         }| j                  d| d|f      j                         }|rt        |d         S dS )NzSELECT z FROM daily_costs WHERE date=?r   r-   )	r   nowr	   utcdate	isoformatr!   fetchonefloat)r   keytodayrows       r   todays_costrL   ~   s`    LL&++-779E
++u$BCeX
N
W
W
YC5Q=(S(r   c                    t        j                  t        j                        j	                         j                         }| j                  d|||||z   ||||z   f       | j                          y )NzINSERT INTO daily_costs (date, triage_usd, deep_usd, total_usd) VALUES (?,?,?,?) ON CONFLICT(date) DO UPDATE SET triage_usd=triage_usd+?, deep_usd=deep_usd+?, total_usd=total_usd+?)r   rC   r	   rD   rE   rF   r!   r"   )r   triage_delta
deep_deltarJ   s       r   add_costrP      sb    LL&++-779EKK	n	j,*C	z<*#<	> JJLr   c                $    | dz  dz  |dz  dz  z   S )Ni@B g      ?g      @ input_tokensoutput_tokenss     r   haiku_pricing_usdrV      s!    9$+}y/HC.OOOr   c                   t        j                         }	 | j                  j                  |dd|dg      }dj                  d |j                  D              }|}d}		 d|v r*|j                  d      d   }|j                  d      r|dd }|j                         }|j                  d      }
|j                  d      }|
dk7  r |dk7  rt        j                   ||
|dz          }	|j&                  j(                  |j&                  j*                  d}t        d||||t        t        j                         |z
  dz        |       |	|fS # t        $ rV}t        d||t        t        j                         |z
  dz        |t        |             dt        |      d	d	d
fcY d}~S d}~ww xY w# t        j"                  t$        f$ r d}	Y w xY w)zCCall Haiku, expect JSON. Returns (parsed_json or None, usage_dict).i  user)rolecontent)model
max_tokensmessagesr   i  )scriptr[   prompt
latency_msvideo_iderrorNr   )rb   rT   rU    c              3  N   K   | ]  }t        |d       s|j                    yw)textN)hasattrre   ).0bs     r   	<genexpr>zcall_haiku.<locals>.<genexpr>   s     J!wq&7IqvvJs   %%z```r   json   {}rS   )r^   r[   r_   response_textusager`   ra   )time	monotonicr]   create	Exceptionr   r4   strjoinrZ   split
startswithstripfindrfindrj   loadsJSONDecodeError
ValueErrorrp   rT   rU   )clientr[   r_   ra   t0resperaw_textre   parsedfirstlastrp   s                r   
call_haikur      s   		B
N%%%&9: & 
 wwJt||JJHDF
D=::e$Q'Dv&ABxzz|		#tzz#B;42:ZZU46 23F 

//11E +5!)!4>>#3b#8D"@AHV 5=5  N/uV"%t~~'7"'<&D"E (A	8 s1vq1MMM	N"   *- s1   "E BF* 	F'AF"F'"F'*GGc                    |d   |d   z   |d   z   |d   z   dz  }| j                  d||d   |d   |d   |d   t        |      |||||f       | j                          y )Nr(   r)   r*   r+   r,   zINSERT OR REPLACE INTO triaged (video_id, depth, novelty, aria_relevance, production_ready, junk_penalty, avg_score, verdict, one_line_reason, triage_path, cost_usd) VALUES (?,?,?,?,?,?,?,?,?,?,?))r!   r4   r"   )	r   ra   r5   r<   reasonpathcostr   avgs	            r   store_triager      s    '?VI..8H1IIFSeLffjm
mCKK 	O	6'?F9$5v>N7OQWXjQkmpq}m~  AD  FM  OU  W[  ]a  	b JJLr   c                    t        | d   d         }|j                  dd       || dz  }|j                  t        j                  |dd             t        |      S )	Npaths
triage_dirT)parentsexist_okz.jsonr/   F)indentensure_ascii)r
   mkdir
write_textrj   dumpsru   )cfgra   payloadout_dirps        r   write_triage_filer      sX    3w<-.GMM$M.XJe$$ALLGAEBCq6Mr   c                \    | j                  d      }| j                          |j                  S )Nz@INSERT INTO run_log (stage, status) VALUES ('triage', 'running'))r!   r"   	lastrowid)r   curs     r   log_run_startr      s$    
++X
YCJJL==r   c                R    | j                  d|||||f       | j                          y )NzUPDATE run_log SET finished_at=datetime('now'), status='completed', items_processed=?, items_skipped=?, items_failed=?, notes=? WHERE id=?r    )r   run_id	processedskippedfailednotess         r   log_run_finishr      s-    KK 	U	GVUF3 JJLr   c                8	   t               }t        |d   d         }t        |       t        j                  j                  d      }|sjt        |d      }t        dt        |       d       t        |       t        ||j                  d      j                         d	   d	t        |      d	d
       y		 d	dlm}  ||      }|d   d   }t!        |d      }||k\  rt        d|dd| d       y	t        |      }|st        d       y	t        dt        |       d||z
  d       t        |      }	|d   d   }
|d   d   }|d   d   }|d   d   }|d   d   }d	}d	}d	}|D ]  }t!        |d      |k\  rt        d         n	 t#        j$                  t'        |d!         j)                               }|j                  d#      xs d$d |
 }|j/                         st1        ||d%   d	d	d	d	d&d'd(d$d)       |d"z  }t2        j5                  |d*   xs d$|d+   xs d$t7        |d,   xs d	d-z        |d.   xs d/|0      }t9        ||||d%   1      \  }}t;        |d2   |d3         }t=        ||4       |rd5|vr6t1        ||d%   d	d	d	d	d&d'd6|j                  d7d$      d d8  d$|       |d"z  }Jt7        |j                  d9d	            t7        |j                  d:d	            t7        |j                  d;d	            t7        |j                  d<d	            d&}t?        d	tA        d=t7        |j                  d>d	                        }tC        |||||      \  }}}|j                  d5      d'k(  rd'}|j                  d?d$      d d@ }|d%   |d+   |d*   ||||||||tE        jF                  tH        jJ                        jM                         dA}tO        ||d%   |      } t1        ||d%   |||| ||       |d"z  }tQ        jR                  dB        t        ||	|||dCt!        |d      d       t        dD| dE| dF| dGt!        |d      d       |jU                          y	# t        $ r t        d       Y yw xY w# t*        t"        j,                  f$ r	 |d"z  }Y 7w xY w)HNr   state_dbANTHROPIC_API_KEYi'  )r@   z([akp-triage] ANTHROPIC_API_KEY not set. z videos queued.zSELECT MAX(id) FROM run_logr   
no_api_key)	Anthropicz9[akp-triage] anthropic SDK missing. pip install anthropicr/   )api_key	cost_capstriage_max_usd
triage_usdz%[akp-triage] daily cost-cap reached (z.4f/z USD). Skipping run.z[akp-triage] no pending videos.z[akp-triage] z pending. cost-budget left: $triagetranscript_max_charspromote_threshold_avgpromote_threshold_ariasummary_threshold_avgmodelstriage_modelz0[akp-triage] cost-cap reached mid-run, stopping.raw_pathr   
transcriptrc   ra   )r(   r)   r*   r+   r.   empty_transcriptr-   titlechannelduration_seconds<   upload_dateunknown)r   r   duration_minr   transcript_excerpt)ra   rT   rU   )rN   r<   zparse_fail: rb   d   r(   r)   r*   r+   r'   r   one_line_reasoni,  )ra   r   r   r5   r   	avg_scoreeffective_scorer<   r   r[   cost_usd
triaged_atg?ztodays_cost=$z[akp-triage] processed=z	 skipped=z failed=z cost_today=$)+r   r   r%   osenvirongetrA   printlenr   r   r!   rG   	anthropicr   ImportErrorrL   rj   r|   r
   	read_textOSErrorr}   ry   r   TRIAGE_PROMPTformatr4   r   rV   rP   r2   r3   r=   r   rC   r	   rD   rF   r   rq   sleepclose)!argvr   r   r   pendingr   r   cost_captodaysr   excerpt_maxr6   r7   r8   r[   r   r   r   rK   rawr   r_   r   rp   r   r5   r   r<   r   r;   r   r   r   s!                                    r   mainr      s~   
-C
#g,z*
+C#jjnn01Gc/8WoVWcsCKK(EFOOQRSTVWY\]dYeghjvw' w'F; 01Hl+F5fS\8*L`ab#G/0	M#g,'DXPVEVWZD[
\]3Fh- 67Kh- 78Kx=!9:Lh- 78KM.)EIFG <\*h6DE	**T#j/2<<>?C ggl+1r<K@
!c*oAWXlm/npv  yK  MO  QT  UqLG%%g,$"	N(bc"45:b@AM*7i) & 
 #65&3z?S ~!6o8NO4(&0c*oAWXlm/npv  {G  HM  HQ  HQ  RY  Z\  H]  ^b  _b  Hc  Gd  ye  gi  ko  paKF GQ/06::i34!&**-=q"AB #FJJ/A1$E F	
 1c!SNA)F%GHI+FL+|]hic::i F*G-r24C8J9~\("%",,x||4>>@
 !c*ow?S#j/67FD$P\]Q	

3y<| 3	7FmKX[\hLijmKn<op	#I;iyP]^ijmnz^{|  ^A  B  CIIK}  IJF --. 	aKF	s$   3Q /Q7Q43Q47RR__main__script_startr   )returndict)r   ru   r   sqlite3.Connection)r   r   r   None)r5   r   r   r4   r6   rH   r7   r4   r8   rH   r   ztuple[str, float, float])   )r   r   r@   r4   r   zlist[sqlite3.Row])r   r   rI   ru   r   rH   )r-   r-   )r   r   rN   rH   rO   rH   r   r   )rT   r4   rU   r4   r   rH   r   )r[   ru   r_   ru   ra   z
str | Noner   ztuple[dict | None, dict])r   )r   r   ra   ru   r5   r   r<   ru   r   ru   r   ru   r   rH   r   r4   r   r   )r   r   ra   ru   r   r   r   ru   )r   r   r   r4   )rc   )r   r   r   r4   r   r4   r   r4   r   r4   r   ru   r   r   )r   z	list[str]r   r4   )-__doc__
__future__r   sys_sysr   insertaria_loggingr   _get_logger_log
aria_auditr   _auditaria_llm_tracer   rj   r   r   rq   r   r   r	   pathlibr
   r   r   r   r   r%   r=   rA   rL   rP   rV   r   r   r   r   r   r   __name__eventexitr   rR   r   r   <module>r      s   
 #  		  $ % 2$% & ) ) ) ) ' :;$N!
&!&&69&!&&+C&4)P
#Lm` zJJ~CHHT#((12,  r   