pyc • Lines: 671�
�Y�j�M � �< � d Z ddlZddlZddlZddlZddlmZ dZ ej d� Z ej d� Z
ej d� Z ej dej � Z
d Zdd
�Zd� Zd� Zd
� Zd� Zd� Zdd�Zd� Zd� Zd� Zd� Zd� Zdd�Zd� Zy)ai Post-generation self-verification ("critic") pass for research answers.
After the LLM emits its final research answer, ``run_verification`` extracts the
structured ``(Author, Venue, Year) [url]`` inline citations, re-fetches each
source and asks a fresh LLM call ("the critic") to check that (1) the source
exists, (2) the claimed author/venue/year metadata matches the real page, and
(3) the specific claim is actually supported by the source text. The resulting
verdict drives a small, local edit of just that sentence (never a full report
rewrite) and a transparent verification trail is appended to the answer.
The pass is always-on for research tasks (no separate toggle) and bounded only
per-citation: at most ``VERIFY_RETRIES`` extra search/fetch attempts per
citation, so a pathological report can never loop forever while keeping the
"no overall cap" behaviour.
� N)�Ma� You are a strict citation fact-checker for a research assistant. Given a claimed citation (URL plus author/venue/year metadata plus one specific claim) and the fetched text of the cited web page, determine: (1) whether the page exists and its topic matches the citation, (2) whether the cited author, venue and year actually appear on the page, (3) whether the exact claim is supported by the page text. Reply with ONLY a JSON object of the form: {"exists": bool, "url_ok": bool, "author_ok": bool, "venue_ok": bool, "year_ok": bool, "claim_support": "supports"|"partial"|"unsupported"|"absent", "corrected_meta": string|null, "reason": string}. "corrected_meta" must be a comma-separated "Author, Venue, Year" string when the metadata is wrong AND the page itself reveals the correct values, otherwise null. "year_ok"/"author_ok"/"venue_ok" must be false only when the page text contradicts the claim, not when the value is merely absent.zK(?P<meta>[\[(][^)\]\[(\n]{0,180}[\]\)])\s*\[(?P<url>https?://[^\s\]<>']+)\]z1(?P<meta>[\[(][^)\]\[(\n]{0,180}[\]\)])\s*\[\s*\]z(?<!\w)(https?://[^\s\]<>()]+)z ```.*?```z2
<details>
<summary>Source verification</summary>c �
� t j |� d| d�d|d�g|ddd�}d}t d� D ]� } t j |� t j
t j |� |d �
� }|j � |j � d d d
j d� }|r|c S d}t d|� d|dz � d|� �� t j d� �� y# t $ r} t | � }Y d} ~ �Hd} ~ ww xY w)u� Secondary, non-streamed, low-temperature LLM call. Retries once and
never raises — returns None only when the model itself is unreachable.�system)�role�content�userg�������?F)�model�messages�
max_tokens�temperature�streamN� �x )�json�timeout�choicesr �messager zempty content in responsez[critic] LLM call failed (mode=z
, attempt � z/2): g �?)r �server_model_id�range�mark_slot_kv_dirty�requests�post�
server_url�raise_for_statusr �get� Exception�str�print�time�sleep)
r r �moder �payload�last_err�attempt�rr �es
�server/features/critic.py�_critic_completionr) 7 s � � �"�"�4�(��&�1���-�
� !��� �G� �H���8� �� �
� � ��&��
�
�a�l�l�4�0�w��L�A�
��� ��f�f�h�y�)�!�,�Y�7�;�;�I�F�G����2�H� �/��v�Z��!��}�E�RZ�Q[�\�]��
�
�3��� �� � ��1�v�H�� �s �A;C$�3C$�$ D�-C=�=Dc � � | syt j dd| � j � }|j d� }|j d� }|dk s||k ry t j |||dz � S # t t f$ r Y yw xY w)zFBest-effort JSON parse of the critic's reply. Returns None on failure.Nz```(?:json)?� �{�}r r ) �re�sub�strip�find�rfindr �loads�
ValueError� TypeError)�text�cleaned�start�ends r( �_parse_verdictr: U s� � ����f�f�_�b�$�/�5�5�7�G��L�L���E�
�-�-��
�C��q�y�C�5�L����z�z�'�%��a��0�1�1��� �"� ���s �A2 �2B�Bc � � g }t � }t j d| xs d� }t |� D �]� \ }}t j d|� }g }t j |� D ]R }|j ||j � |j � d|j d� j � d�� �T t j |� D ]� }|j d� j d� } | |v r�(|j | � ||j � |j � | |j d� j � d�}
|j |
� |j | j d� � �� t j |� D ]o }|j d� j d� } | |v s| |v r�,|j | � |j ||j � |j � | dd�� �q ��� |S ) ag Return a list of citation dicts found in the answer.
Each dict is ``{idx, start, end, url, meta, prepared}`` where ``idx`` is the
paragraph index in ``answer`` split on blank lines, ``start``/``end`` are
offsets inside that paragraph, and ``meta`` is the "(Author, Venue, Year)"
text (or None for a bare URL). Duplicate URLs are ignored.
�
\s*\n\s*\n\s*r+ �meta)�idxr8 r9 �urlr= r? �.,;:]r N)�setr. �split� enumerate�_CODE_FENCE_REr/ �_EMPTY_CITE_RE�finditer�appendr8 r9 �groupr0 �_META_RE�rstrip�add�
_PLAIN_URL_RE)�answer� citations�seen�parasr>