Ë
    ¥©	j['  ã            	       óÐ   — U d Z ddlZddlmZ ddlmZ ddlmZ ddlm	Z	m
Z
mZ  ee«      Zddd	d
œdddd
œdddd
œdddd
œdddd
œdddd
œdœZ G d„ d«      Zdaedz  ed<   defd„Zy) z„
Voice rewriter service - uses Granite to add character personality to findings.
Each character has a unique voice and perspective.
é    N)Úget_watsonx_client)Úsettings)Ú
get_logger)ÚCharacterIdÚFindingÚFindingValidatedzAegis, the Security PaladinzZNoble, vigilant, speaks in terms of threats and defenses. Uses medieval/fantasy metaphors.zpThis vulnerability is a breach in thy defenses! An attacker could exploit this weakness to infiltrate thy realm.)ÚnameÚpersonalityÚexamplezSchema, the Database MagezZWise, analytical, speaks about data flow and optimization. Uses arcane/mystical metaphors.z{The data flows inefficiently through these channels. I sense an N+1 query curse that will drain thy application's vitality.zPixel, the UX BardzfArtistic, empathetic, speaks about user experience and accessibility. Uses musical/artistic metaphors.zˆThe contrast here creates a discordant note in the user's journey. Those with visual impairments will struggle to perceive this element.z Atlas, the Architecture Explorerz_Strategic, systematic, speaks about structure and patterns. Uses exploration/mapping metaphors.ztI've charted these dependencies, and they form a tangled web. This coupling will make future navigation treacherous.zEcho, the Test Priestz]Methodical, thorough, speaks about validation and edge cases. Uses ritual/ceremony metaphors.zrThis code path lacks the sacred rites of testing. What happens when the input is null? The ceremony is incomplete.zCodex, the Docs Scribez^Scholarly, precise, speaks about clarity and documentation. Uses library/manuscript metaphors.z…The scrolls are silent on this function's purpose. Future scholars will struggle to decipher its intent without proper documentation.)ÚaegisÚschemaÚpixelÚatlasÚechoÚcodexc                   ód   — e Zd ZdZd„ Zdededefd„Zdededefd„Z	de
eee   f   dee   fd	„Zy
)ÚVoiceRewriterzERewrites technical findings with character personality using Granite.c                 óL   — t        «       | _        t        j                  d«       y )NÚvoice_rewriter_initialized)r   ÚwatsonxÚloggerÚinfo)Úselfs    ú</var/www/html/prparty/backend/app/services/voice_rewriter.pyÚ__init__zVoiceRewriter.__init__5   s   € Ü)Ó+ˆŒÜ�‰Ð0Õ1ó    Úcharacter_idÚfindingÚreturnc                 óv   — t         |   }d|d   › d|d   › d|d   › d|j                  › d|j                  › d	�}|S )
zABuild prompt for Granite to rewrite finding in character's voice.zYou are r	   z.

Personality: r
   z1

Reference style (do not repeat this sentence): r   u”  

Your task: Rewrite the following technical finding in your unique voice. Keep it concise (2-3 sentences max). Maintain the technical accuracy but add your personality. Respond with ONLY the rewritten comment as a single short paragraph â€” no quotation marks around it, no meta-commentary, no further examples, no offers to rewrite more findings, no questions, no follow-up.

Technical Finding:
Title: z
Description: z&

Your voiced comment (2-3 sentences):)ÚCHARACTER_VOICESÚtitleÚdescription)r   r   r   Ú	characterÚprompts        r   Ú_build_voice_promptz!VoiceRewriter._build_voice_prompt9   sp   € ô % \Ñ2ˆ	à˜i¨Ñ/Ð0ð 1à˜Ñ&Ð'ð (0à09¸)Ñ0DÐ/Eð Fð
 	�‰€ð Ø×!Ñ!Ð"ð #%ð(ˆð ˆr   c           	   ƒ   óê  K  — t         j                  d||j                  ¬«       | j                  ||«      }	 | j                  j                  t        j                  |ddg d¢¬«      ƒ d{  –—† }|j                  «       j                  d«      j                  d	«      j                  «       }t        j                  d
|«      }|r7|j                  «       dk\  r$|d|j                  «       dz    j                  «       }g d¢}|D ][  }|j                  |«      }|dkD  sŒ|d| j                  «       }	|	j                  d«      j                  d	«      j                  «       } n g d¢}
|
D ]Y  }|j                  |«      }|dkD  sŒ|d| j                  «       j                  d«      j                  d	«      j                  «       } n dD ].  }|j                  |«      }|t        |«      dz  kD  sŒ&|d|dz    } n t         j                  d||j                  t        |«      ¬«       |S 7 �Œ·# t         $ rB}t         j#                  d||j                  t%        |«      ¬«       |j&                  cY d}~S d}~ww xY w­w)a  
        Rewrite a finding in the character's voice using Granite.
        
        Args:
            character_id: Character to voice the finding
            finding: Technical finding to rewrite
        
        Returns:
            Character's voiced dialogue
        Úvoice_rewrite_start)r   Ú
finding_idé–   gš™™™™™é?)ú

ú
Title:ú
Exampleú
HereúExample soundsúYour response should)Úmodel_idr%   Ú
max_tokensÚtemperatureÚstop_sequencesNú"ú'z([.!?])"\s+[A-Z]é   é   )r/   zExample wasr0   zHere's anotherzHere is anotherzHere's a newzHere is a newzHere are a fewzHere are morezHere is the proposedzHere is the rephrasedz	Your turnz	your turnzHow was thatzWas thatr   )r,   z
Description:r-   z
Yourr.   z
Nowz
I,r+   )ú.ú!Ú?é   Úvoice_rewrite_complete)r   r)   Údialogue_lengthÚvoice_rewrite_error)r   r)   Úerror)r   r   Úidr&   r   Úgenerate_textr   Úgranite_model_idÚstripÚreÚsearchÚstartÚfindÚrstripÚrfindÚlenÚ	Exceptionr@   Ústrr#   )r   r   r   r%   ÚdialogueÚ	quote_cutÚinline_phrasesÚphraseÚidxÚheadÚnewline_markersÚmarkerÚpuncÚlastÚes                  r   Úrewrite_findingzVoiceRewriter.rewrite_findingQ   sm  è ø€ ô 	�‰Ø!Ø%Ø—z‘zð 	ô 	
ð ×)Ñ)¨,¸Ó@ˆðW	'Ø!Ÿ\™\×7Ñ7Ü!×2Ñ2ØØØò ð 8ó ÷ ˆHð$  —~‘~Ó'×-Ñ-¨cÓ2×8Ñ8¸Ó=×CÑCÓEˆHô Ÿ	™	Ð"5°xÓ@ˆIÙ˜YŸ_™_Ó.°"Ò4Ø#Ð$; i§o¡oÓ&7¸!Ñ&;Ð<×BÑBÓD�ò
	ˆNð )ò �Ø—m‘m FÓ+�Ø˜“7Ø# D S˜>×0Ñ0Ó2�DØ#Ÿ{™{¨3Ó/×6Ñ6°sÓ;×BÑBÓD�HÙðòˆOð *ò �Ø—m‘m FÓ+�Ø˜“7Ø'¨¨˜~×4Ñ4Ó6×=Ñ=¸cÓB×IÑIÈ#ÓN×UÑUÓW�HÙð	ð (ò �Ø—~‘~ dÓ+�Øœ#˜h›-¨1Ñ,Ó,Ø'¨	¨°©Ð2�HÙð	ô �K‰KØ(Ø)Ø"Ÿ:™:Ü # H£ð	 ô ð ˆOðYúô\ ò 	'Ü�L‰LØ%Ø)Ø"Ÿ:™:Ü˜!“fð	 ô ð ×&Ñ&Õ&ûð	'üs[   ‚5I3¸3H% Á+H"Á,B.H% ÄA#H% Å?A)H% Ç)8H% È!I3È"H% È%	I0È.7I+É%I0É&I3É+I0É0I3Úclassified_findingsc              ƒ   óà  K  — g }|j                  «       D ]²  \  }}|D ]¨  }| j                  ||«      ƒ d{  –—† }t        |j                  |j                  |j
                  |j                  |j                  |j                  |j                  |j                  |j                  |j                  ||¬«      }|j                  |«       Œª Œ´ t        j                  dt!        |«      ¬«       |S 7 Œ¶­w)zè
        Rewrite all findings with character voices.
        
        Args:
            classified_findings: Findings grouped by character
        
        Returns:
            List of findings with character_dialogue added
        N)rA   r"   r#   ÚseverityÚdamageÚdamage_typeÚ	file_pathÚ
line_startÚline_endÚcode_snippetr   Úcharacter_dialogueÚall_findings_voiced)Útotal_findings)ÚitemsrY   r   rA   r"   r#   r\   r]   r^   r_   r`   ra   rb   Úappendr   r   rK   )r   rZ   Úvoiced_findingsr   Úfindingsr   rN   Úvoiced_findings           r   Úrewrite_findingszVoiceRewriter.rewrite_findingsÁ   sð   è ø€ ð *,ˆà&9×&?Ñ&?Ó&Aò 	7Ñ"ˆL˜(Ø#ò 7�à!%×!5Ñ!5°lÀGÓ!L×L�ô ")Ø—z‘zØ!Ÿ-™-Ø '× 3Ñ 3Ø$×-Ñ-Ø"Ÿ>™>Ø '× 3Ñ 3Ø%×/Ñ/Ø&×1Ñ1Ø$×-Ñ-Ø!(×!5Ñ!5Ø!-Ø'/ô"�ð  ×&Ñ& ~Õ6ñ)7ð	7ô. 	�‰Ø!Ü˜Ó/ð 	ô 	
ð
 Ðð3 Mús   ‚3C.µC,¶B7C.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   rM   r&   rY   ÚdictÚlistr   rk   © r   r   r   r   2   s|   „ ÙOò2ðà!ðð "ðð 
ó	ð0n'à!ðn'ð "ðn'ð 
ó	n'ð`+à! +¨tÐ4DÑ/EÐ"EÑFð+ð 
ˆg‰ô+r   r   Ú_voice_rewriterr   c                  ó.   — t         €
t        «       a t         S )z-Get or create global voice rewriter instance.)rs   r   rr   r   r   Úget_voice_rewriterru   ó   s   € ô ÐÜ'›/ˆÜÐr   )ro   rE   Úapp.clients.watsonx_clientr   Ú
app.configr   Úapp.logging_configr   Ú
app.modelsr   r   r   rl   r   r!   r   rs   Ú__annotations__ru   rr   r   r   ú<module>r{      sÍ   ðòó 
å 9Ý Ý )ß =Ñ =á	�HÓ	€ð .Øsð Fñð ,Øsð Qñð %Øð ^ñð 3Øxð Jñð (Øvð Hñð )Øwð [ññ5Ð ÷Dzñ zð| )-€� Ñ%Ó ,ð˜Mô r   