Spaces:
Running
Running
| import sys | |
| import os | |
| import time | |
| import asyncio | |
| from unittest.mock import patch, MagicMock | |
| sys.path.append(os.path.dirname(os.path.abspath(__file__))) | |
| from endpoints.projects import autofix_project_section | |
| from fastapi import HTTPException | |
| # Mock klas | |
| class DummyProject: | |
| id = "proj_1" | |
| clerk_user_id = "clerk_123" | |
| title = "Projekt Testowy" | |
| program_type = "SMART" | |
| final_document_audit_result = { | |
| "issues": [ | |
| { | |
| "affected_section": "Ogólne", | |
| "severity": "high", | |
| "category": "logic", | |
| "message": "Brak spójności", | |
| "recommendation": "Popraw spójność", | |
| } | |
| ] | |
| } | |
| external_context = {} | |
| class DummySection: | |
| id = "sec_1" | |
| project_id = "proj_1" | |
| section_type = "project_summary" | |
| content = "Oryginalna treść sekcji." | |
| class DummyQuery: | |
| def __init__(self, model): | |
| self.model = model | |
| def filter(self, *args, **kwargs): | |
| return self | |
| def join(self, *args, **kwargs): | |
| return self | |
| def first(self): | |
| if hasattr(self.model, "__name__"): | |
| if self.model.__name__ == "Project": | |
| return DummyProject() | |
| elif self.model.__name__ == "ProjectSection": | |
| return DummySection() | |
| return None | |
| def all(self): | |
| return [] | |
| class DummyDB: | |
| def query(self, model, *args, **kwargs): | |
| return DummyQuery(model) | |
| def add(self, obj): | |
| pass | |
| def commit(self): | |
| pass | |
| def refresh(self, obj): | |
| pass | |
| def run_simulation(): | |
| print("==================================================") | |
| print("[SYMULACJA] BŁĘDÓW 429 (RATE LIMIT) LLM W AUTOFIX") | |
| print("==================================================") | |
| db = DummyDB() | |
| call_count = 0 | |
| # Mock dla metody invoke w łańcuchu LangChain | |
| def mock_chain_invoke(*args, **kwargs): | |
| nonlocal call_count | |
| call_count += 1 | |
| print(f"\n[LLM Request] Próba nr {call_count}...") | |
| if call_count < 3: | |
| print( | |
| "[LLM Error] Symulowanie bledu: 429 ResourceExhausted (Przekroczono limit Quota)" | |
| ) | |
| # Rzucamy wyjątek, który backend normalnie by dostał od Google API | |
| raise Exception("429 ResourceExhausted: Quota exceeded for AI") | |
| print("[LLM Success] Zwracanie poprawnej odpowiedzi na 3. probie!") | |
| mock_response = MagicMock() | |
| mock_response.content = ( | |
| "Zaktualizowana i poprawiona treść sekcji z uwzględnieniem audytu." | |
| ) | |
| return mock_response | |
| # Ponieważ 'chain' jest tworzony wewnątrz funkcji, zrobimy patch na PromptTemplate.__or__ | |
| # albo bezpośrednio na klasie RunnableSequence | |
| with patch("endpoints.projects.get_llm") as mock_get_llm: | |
| # Konstruujemy mockowany LLM | |
| mock_llm = MagicMock() | |
| mock_get_llm.return_value = mock_llm | |
| # Zamiast patchować '|' (or), po prostu zrobimy patch na chain.invoke | |
| # w Pythonie możemy użyć mocka na całej klasie PromptTemplate, ale łatwiej patchować llm | |
| # Mockujemy zachowanie łańcucha prompt | llm | |
| # W Langchain operator | tworzy RunnableSequence. Mockujemy zachowanie invoke na wyniku | |
| with patch( | |
| "endpoints.projects.PromptTemplate.from_template" | |
| ) as mock_from_template: | |
| mock_prompt = MagicMock() | |
| mock_from_template.return_value = mock_prompt | |
| mock_chain = MagicMock() | |
| mock_chain.invoke.side_effect = mock_chain_invoke | |
| mock_prompt.__or__.return_value = mock_chain | |
| # Należy też zmockować ProjectSectionVersion | |
| with patch("endpoints.projects.ProjectSectionVersion"): | |
| try: | |
| start_time = time.time() | |
| # Nowa sygnatura funkcji | |
| result = asyncio.run( | |
| autofix_project_section( | |
| project_id="proj_1", | |
| section_id="sec_1", | |
| token_data={"sub": "clerk_123"}, | |
| db=db, | |
| ) | |
| ) | |
| end_time = time.time() | |
| print("\n==================================================") | |
| print("[WYNIK SYMULACJI]") | |
| print("Status: SUKCES (Udało się przetrwać błędy 429!)") | |
| print( | |
| f"Całkowity czas wykonania: {end_time - start_time:.2f} sekund" | |
| ) | |
| print(f"Zwrócony tekst:\n{result.content}") | |
| print("==================================================") | |
| except HTTPException as e: | |
| print( | |
| f"\n[Frontend Error] Funkcja rzucila HTTP 429 do Frontendu po wyczerpaniu limitu prob: {e.detail}" | |
| ) | |
| if __name__ == "__main__": | |
| run_simulation() | |