Ë
    Ï,j  ã                  óÀ   — d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
m
Z
 ddlmZmZ ddlZddlmZ ddlmZ ddlmZ ddd	„Zdd
„Zdd„Z G d„ d«      Z G d„ d«      Zy)z?Tests for the OpenAI-based extractor with mocked API responses.é    )ÚannotationsN)Údatetime)Ú	MagicMockÚpatch)ÚSettings)Úextract_with_openai)ÚPostc                ó<   — t        d|dd| t        ddd«      d¬«      S )	NÚtest_001z	Test Userzhttps://fb.com/testié  é   é   zhttps://fb.com/posts/001)Úpost_idÚgroupÚauthor_nameÚauthor_profile_urlÚtextÚ	timestampÚpost_url)r	   r   )r   r   s     ú>/var/www/html/agent.samochodowy/tests/test_openai_extractor.pyÚ_postr      s-   € ÜØØØØ0ØÜ˜4  BÓ'Ø+ôð ó    c                 óF   — ddddœ}|j                  | «       t        di |¤ŽS )Nzsk-test-fake-keyÚopenaiúgpt-4o-mini)Úllm_api_keyÚllm_providerÚ	llm_model© )Úupdater   )Ú	overridesÚdefaultss     r   Ú	_settingsr"      s.   € à)Ø Ø"ñ€Hð
 ‡O�O�IÔÜÑ�hÑÐr   c                óî   — t        «       }d|j                  _        t        j                  | «      |j                  _        t        «       }|g|_        t        «       }||_        t        «       }|g|_        |S )z:Build a mock ChatCompletion response with a function call.Úextract_part_query)	r   ÚfunctionÚnameÚjsonÚdumpsÚ	argumentsÚ
tool_callsÚmessageÚchoices)ÚdataÚ	tool_callr+   ÚchoiceÚresponses        r   Ú_mock_openai_responser1   &   sc   € ä“€IØ2€I×ÑÔÜ#'§:¡:¨dÓ#3€I×ÑÔ ä‹k€GØ#˜€GÔä‹[€FØ€F„Nä‹{€HØ�x€HÔØ€Or   c                  ó´   — e Zd Z ed«      d„ «       Z ed«      d„ «       Z ed«      d„ «       Z ed«      d„ «       Z ed«      d„ «       Z ed«      d„ «       Z	y)	ÚTestOpenAIExtractorz;agent_samochodowy.extraction.openai_extractor.openai.OpenAIc                ó®	  — t        «       }||_        t        dddd dd dgddœ«      |j                  j                  j
                  _        t        t        d«      t        «       «      }|j                  }d}||u }|s­t        j                  d	|fd
||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚d x}x}}|j$                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚d x}x}}|j&                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚d x}x}}|j(                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚d x}x}}d}	|j*                  }|	|v }
|
s­t        j                  d|
fd|	|f«      t        j                  |	«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚d x}	x}
}|j,                  }|syddt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dœz  }t!        t        j"                  |«      «      ‚d }y )NTÚVOLVOÚFH13z
pompa wodyÚ20744939u7   UÅ¼ytkownik szuka pompy wody do Volvo FH13 z numerem OE©Úis_part_requestÚbrandÚmodelÚyearÚcategoryÚengine_codeÚ
oe_numbersÚreasonz7Szukam pompy wody do Volvo FH13, numer 20744939. Pilne!©Úis©z7%(py2)s
{%(py2)s = %(py0)s.is_part_request
} is %(py5)sÚresult©Úpy0Úpy2Úpy5úassert %(py7)sÚpy7©ú==©z-%(py2)s
{%(py2)s = %(py0)s.brand
} == %(py5)s)z-%(py2)s
{%(py2)s = %(py0)s.model
} == %(py5)s)z0%(py2)s
{%(py2)s = %(py0)s.category
} == %(py5)s©Úin©z2%(py1)s in %(py5)s
{%(py5)s = %(py3)s.oe_numbers
}©Úpy1Úpy3rH   z*assert %(py2)s
{%(py2)s = %(py0)s.reason
})rF   rG   )r   Úreturn_valuer1   ÚchatÚcompletionsÚcreater   r   r"   r9   Ú
@pytest_arÚ_call_reprcompareÚ@py_builtinsÚlocalsÚ_should_repr_global_nameÚ	_safereprÚAssertionErrorÚ_format_explanationr:   r;   r=   r?   r@   )ÚselfÚmock_openai_clsÚmock_clientrD   Ú@py_assert1Ú@py_assert4Ú@py_assert3Ú@py_format6Ú@py_format8Ú@py_assert0Ú@py_assert2Ú@py_format3s               r   Útest_extracts_part_requestz.TestOpenAIExtractor.test_extracts_part_request8   sÜ  € ä“kˆØ'2ˆÔ$Ü;PØ#ØØØØ$ØØ%˜,ØOñ	R
ó 	<ˆ×Ñ×$Ñ$×+Ñ+Ô8ô %ÜÐKÓLÜ‹Kó
ˆð
 ×%Ñ%Ð-¨Ð-Ð%¨Ð-×-×-Õ-Ð%¨×-×-×-×-×-Ñ-ˆv×-×-Ó-ˆv×-×-Ô-Ð%×-×-Ò-¨×-×-×-×-×-×-Ó-Ø�|‰|Ð&˜wÐ&ˆ|˜wÑ&×&×&Õ&ˆ|˜w×&×&×&×&×&Ñ&ˆv×&×&Ó&ˆv×&×&Ô&ˆ|×&×&Ò&˜w×&×&×&×&×&×&Ó&Ø�|‰|Ð%˜vÐ%ˆ|˜vÑ%×%×%Õ%ˆ|˜v×%×%×%×%×%Ñ%ˆv×%×%Ó%ˆv×%×%Ô%ˆ|×%×%Ò%˜v×%×%×%×%×%×%Ó%Ø�‰Ð. ,Ð.ˆ ,Ñ.×.×.Õ.ˆ ,×.×.×.×.×.Ñ.ˆv×.×.Ó.ˆv×.×.Ô.ˆ×.×.Ò. ,×.×.×.×.×.×.Ó.ØÐ.˜V×.Ñ.Ð.ˆzÐ.Ð.×.×.Õ.ˆzÐ.×.×.Ó.ˆz×.×.×.×.×.Ð.˜V×.×.Ó.˜V×.×.Ô.Ð.×.×.×.×.×.×.Ó.Ø�}‰}Ð‰}××××Õˆv××Óˆv××Ôˆ}×××××Ñr   c                ó\  — t        «       }||_        t        dddd dd g ddœ«      |j                  j                  j
                  _        t        t        d«      t        «       «      }|j                  }d}||u }|s­t        j                  d|fd	||f«      d
t        j                  «       v st        j                  |«      rt        j                  |«      nd
t        j                  |«      t        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚d x}x}}y )NFÚMANÚTGAzklocki hamulcoweu*   Post sprzedaÅ¼owy, nie zapytanie kupujÄ…cer8   u0   Sprzedam klocki hamulcowe MAN TGA, nowe, 200 zÅ‚rA   rC   rD   rE   rI   rJ   )r   rT   r1   rU   rV   rW   r   r   r"   r9   rX   rY   rZ   r[   r\   r]   r^   r_   ©	r`   ra   rb   rD   rc   rd   re   rf   rg   s	            r   Útest_rejects_selling_postz-TestOpenAIExtractor.test_rejects_selling_postS   sÜ   € ä“kˆØ'2ˆÔ$Ü;PØ$ØØØØ*ØØØBñ	R
ó 	<ˆ×Ñ×$Ñ$×+Ñ+Ô8ô %ÜÐDÓEÜ‹Kó
ˆð
 ×%Ñ%Ð.¨Ð.Ð%¨Ð.×.×.Õ.Ð%¨×.×.×.×.×.Ñ.ˆv×.×.Ó.ˆv×.×.Ô.Ð%×.×.Ò.¨×.×.×.×.×.×.Ô.r   c                ó|  — t        «       }||_        t        dddd ddg ddœ«      |j                  j                  j
                  _        t        t        d«      t        «       «      }|j                  }d}||u }|s­t        j                  d	|fd
||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚d x}x}}|j$                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚d x}x}}|j&                  }d}||k(  }|s­t        j                  d|fd||f«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚d x}x}}y )NTÚOPELzAstra FÚ
alternatorÚC18NZz&Zapytanie o alternator z kodem silnikar8   u/   KupiÄ™ alternator do Opla Astry F, silnik C18NZrA   rC   rD   rE   rI   rJ   rK   )z3%(py2)s
{%(py2)s = %(py0)s.engine_code
} == %(py5)srM   )r   rT   r1   rU   rV   rW   r   r   r"   r9   rX   rY   rZ   r[   r\   r]   r^   r_   r>   r:   ro   s	            r   Útest_handles_engine_codez,TestOpenAIExtractor.test_handles_engine_codei   s»  € ä“kˆØ'2ˆÔ$Ü;PØ#ØØØØ$Ø"ØØ>ñ	R
ó 	<ˆ×Ñ×$Ñ$×+Ñ+Ô8ô %ÜÐCÓDÜ‹Kó
ˆð
 ×%Ñ%Ð-¨Ð-Ð%¨Ð-×-×-Õ-Ð%¨×-×-×-×-×-Ñ-ˆv×-×-Ó-ˆv×-×-Ô-Ð%×-×-Ò-¨×-×-×-×-×-×-Ó-Ø×!Ñ!Ð, WÐ,Ð! WÑ,×,×,Õ,Ð! W×,×,×,×,×,Ñ,ˆv×,×,Ó,ˆv×,×,Ô,Ð!×,×,Ò, W×,×,×,×,×,×,Ó,Ø�|‰|Ð%˜vÐ%ˆ|˜vÑ%×%×%Õ%ˆ|˜v×%×%×%×%×%Ñ%ˆv×%×%Ó%ˆv×%×%Ô%ˆ|×%×%Ò%˜v×%×%×%×%×%×%Ô%r   c                óî  — t        «       }||_        t        ddddddddgddœ«      |j                  j                  j
                  _        t        t        d«      t        «       «      }d}|j                  }||v }|s­t        j                  d	|fd
||f«      t        j                  |«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚dx}x}}d}|j                  }||v }|s­t        j                  d	|fd
||f«      t        j                  |«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dœz  }dd|iz  }t!        t        j"                  |«      «      ‚dx}x}}y)z>OE numbers should be stripped of spaces/dashes and uppercased.TNz51.06500-6408zA 000 180 27 01zOE numbers in textr8   z)Szukam 51.06500-6408 albo A 000 180 27 01Ú51065006408rN   rP   rD   rQ   rI   rJ   ÚA0001802701)r   rT   r1   rU   rV   rW   r   r   r"   r?   rX   rY   r]   rZ   r[   r\   r^   r_   )	r`   ra   rb   rD   rh   rd   ri   rf   rg   s	            r   Útest_oe_normalizationz)TestOpenAIExtractor.test_oe_normalization�   sV  € ô  “kˆØ'2ˆÔ$Ü;PØ#ØØØØØØ*Ð,=Ð>Ø*ñ	R
ó 	<ˆ×Ñ×$Ñ$×+Ñ+Ô8ô %ÜÐ=Ó>Ü‹Kó
ˆð
 Ð1 × 1Ñ 1Ð1ˆ}Ð 1Ð1×1×1Õ1ˆ}Ð 1×1×1Ó1ˆ}×1×1×1×1×1Ð1 ×1×1Ó1 ×1×1Ô1Ð 1×1×1×1×1×1×1Ó1ØÐ1 × 1Ñ 1Ð1ˆ}Ð 1Ð1×1×1Õ1ˆ}Ð 1×1×1Ó1ˆ}×1×1×1×1×1Ð1 ×1×1Ó1 ×1×1Ô1Ð 1×1×1×1×1×1×1Ô1r   c                ó   — t        «       }||_        t        «       }d|_        t        «       }||_        t        «       }|g|_        ||j
                  j                  j                  _        t        t        d«      t        «       «      }|j                  }d}||u }	|	s­t        j                  d|	fd||f«      dt        j                  «       v st        j                   |«      rt        j"                  |«      ndt        j"                  |«      t        j"                  |«      dœz  }
dd	|
iz  }t%        t        j&                  |«      «      ‚dx}x}	}y)
z=When OpenAI returns no function call, treat as not a request.NzRandom textFrA   rC   rD   rE   rI   rJ   )r   rT   r*   r+   r,   rU   rV   rW   r   r   r"   r9   rX   rY   rZ   r[   r\   r]   r^   r_   )r`   ra   rb   r+   r/   r0   rD   rc   rd   re   rf   rg   s               r   Útest_no_tool_call_returns_falsez3TestOpenAIExtractor.test_no_tool_call_returns_false™   sà   € ô  “kˆØ'2ˆÔ$ä“+ˆØ!ˆÔÜ“ˆØ ˆŒÜ“;ˆØ"˜8ˆÔØ;Cˆ×Ñ×$Ñ$×+Ñ+Ô8ä$¤U¨=Ó%9¼9»;ÓGˆØ×%Ñ%Ð.¨Ð.Ð%¨Ð.×.×.Õ.Ð%¨×.×.×.×.×.Ñ.ˆv×.×.Ó.ˆv×.×.Ô.Ð%×.×.Ò.¨×.×.×.×.×.×.Ô.r   c                ó:  — t        «       }||_        t        ddddddg ddœ«      |j                  j                  j
                  _        t        t        d«      t        d¬«      «       |j                  j                  j
                  j                  j                  }|d   }d}||k(  }|slt        j                  d|fd	||f«      t        j                  |«      t        j                  |«      d
œz  }dd|iz  }t        t        j                  |«      «      ‚dx}x}}y)z;Verify the model parameter is passed through from settings.FNÚtestr8   r   )r   r;   rK   )z%(py1)s == %(py4)s)rR   Úpy4zassert %(py6)sÚpy6)r   rT   r1   rU   rV   rW   r   r   r"   Ú	call_argsÚkwargsrX   rY   r]   r^   r_   )	r`   ra   rb   Úcall_kwargsrh   re   ri   Ú@py_format5Ú@py_format7s	            r   Útest_passes_correct_modelz-TestOpenAIExtractor.test_passes_correct_modelª   sÖ   € ô  “kˆØ'2ˆÔ$Ü;PØ$Ø D°$Ø¨TØ¨ñ	R
ó <ˆ×Ñ×$Ñ$×+Ñ+Ô8ô 	œE &›M¬9¸}Ô+MÔNà!×&Ñ&×2Ñ2×9Ñ9×CÑC×JÑJˆØ˜7Ñ#Ð4 }Ð4Ð# }Ñ4×4×4Õ4Ð# }×4×4Ó4Ð#×4×4Ò4 }×4×4×4×4×4×4Ô4r   N)
Ú__name__Ú
__module__Ú__qualname__r   rk   rp   ru   ry   r{   r…   r   r   r   r3   r3   7   s¢   „ Ù
ÐHÓIñó Jðñ4 ÐHÓIñ/ó Jð/ñ* ÐHÓIñ&ó Jð&ñ. ÐHÓIñ2ó Jð2ñ. ÐHÓIñ/ó Jð/ñ  ÐHÓIñ5ó Jñ5r   r3   c                  óH   — e Zd ZdZ ed«      d„ «       Z ed«      d„ «       Zy)ÚTestProviderDispatchz6Test that extraction/__init__.py dispatches correctly.zAagent_samochodowy.extraction.openai_extractor.extract_with_openaic                óŽ   — ddl m} t        d¬«      |_        t	        d¬«      } |t        d«      |«       |j                  «        y )Nr   ©Ú_extract_with_llmF©r9   r   ©r   r}   ©Úagent_samochodowy.extractionr�   r   rT   r"   r   Úassert_called_once©r`   Úmock_extractr�   Úsettingss       r   Útest_openai_dispatchz)TestProviderDispatch.test_openai_dispatch¿   s6   € åBä$-¸eÔ$DˆÔ!Ü¨(Ô3ˆÙœ% ›-¨Ô2Ø×'Ñ'Õ)r   z;agent_samochodowy.extraction.llm_extractor.extract_with_llmc                óŽ   — ddl m} t        d¬«      |_        t	        d¬«      } |t        d«      |«       |j                  «        y )Nr   rŒ   FrŽ   Ú	anthropicr�   r}   r�   r“   s       r   Útest_anthropic_dispatchz,TestProviderDispatch.test_anthropic_dispatchÈ   s6   € åBä$-¸eÔ$DˆÔ!Ü¨+Ô6ˆÙœ% ›-¨Ô2Ø×'Ñ'Õ)r   N)r†   r‡   rˆ   Ú__doc__r   r–   r™   r   r   r   rŠ   rŠ   ¼   s9   „ Ù@á
ÐNÓOñ*ó Pð*ñ ÐHÓIñ*ó Jñ*r   rŠ   )u   TIR czÄ™Å›ci zamienne)r   Ústrr   r›   Úreturnr	   )rœ   r   )r-   Údictrœ   r   )rš   Ú
__future__r   ÚbuiltinsrZ   Ú_pytest.assertion.rewriteÚ	assertionÚrewriterX   r'   r   Úunittest.mockr   r   ÚpytestÚagent_samochodowy.configr   Ú-agent_samochodowy.extraction.openai_extractorr   Úagent_samochodowy.modelsr	   r   r"   r1   r3   rŠ   r   r   r   ú<module>r¨      sJ   ðÙ Eå "ç  „ ƒÝ ß *ã å -Ý MÝ )ô	ó ó÷"B5ñ B5÷J*ò *r   