-
Notifications
You must be signed in to change notification settings - Fork 23
Issue 4: Feature/chainlit UI enhancement #26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 3.10 | ||
| 3.11.6 |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,43 +1,118 @@ | ||||||||||||||||||||||||||||||||
| import chainlit as cl | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| from src.verifact_manager import VerifactManager | ||||||||||||||||||||||||||||||||
| import logging | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| logging.basicConfig(level=logging.INFO) | ||||||||||||||||||||||||||||||||
| logger = logging.getLogger(__name__) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| pipeline = VerifactManager() | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| @cl.on_message | ||||||||||||||||||||||||||||||||
| async def handle_message(message: cl.Message): | ||||||||||||||||||||||||||||||||
| progress_msg = cl.Message(content="Starting fact-checking pipeline...") | ||||||||||||||||||||||||||||||||
| await progress_msg.send() | ||||||||||||||||||||||||||||||||
| progress_updates = [] | ||||||||||||||||||||||||||||||||
| # This dictionary will hold ALL our step objects for the duration of the run | ||||||||||||||||||||||||||||||||
| steps = {} | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # This will act like a stack to keep track of the current active step | ||||||||||||||||||||||||||||||||
| active_step_id_stack = [] | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| async def progress_callback(type: str, data: dict): | ||||||||||||||||||||||||||||||||
| nonlocal steps, active_step_id_stack | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if type == "step_start": | ||||||||||||||||||||||||||||||||
| parent_id = active_step_id_stack[-1] if active_step_id_stack else None | ||||||||||||||||||||||||||||||||
| logger.info(f"Starting step: {data['title']}") | ||||||||||||||||||||||||||||||||
| step = cl.Step(name=data["title"], parent_id=parent_id, id=data["title"]) | ||||||||||||||||||||||||||||||||
| steps[data["title"]] = step | ||||||||||||||||||||||||||||||||
| active_step_id_stack.append(step.id) # Push new step to stack | ||||||||||||||||||||||||||||||||
|
Comment on lines
+25
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Step IDs should be globally unique – titles are not Using -from uuid import uuid4
-...
- step = cl.Step(name=data["title"], parent_id=parent_id, id=data["title"])
+from uuid import uuid4
+...
+ step = cl.Step(name=data["title"], parent_id=parent_id, id=str(uuid4()))📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| logger.info(f"Step stack after push: {active_step_id_stack}") | ||||||||||||||||||||||||||||||||
| await step.send() | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| elif type == "step_end": | ||||||||||||||||||||||||||||||||
| step_id = active_step_id_stack.pop() # Pop current step from stack | ||||||||||||||||||||||||||||||||
| step = steps[step_id] | ||||||||||||||||||||||||||||||||
| step.output = data["output"] | ||||||||||||||||||||||||||||||||
| await step.update() | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| async def progress_callback(msg, update): | ||||||||||||||||||||||||||||||||
| progress_updates.append(update) | ||||||||||||||||||||||||||||||||
| msg.content = "\n".join(progress_updates) | ||||||||||||||||||||||||||||||||
| await msg.update() | ||||||||||||||||||||||||||||||||
| elif type == "step_error": | ||||||||||||||||||||||||||||||||
| step_id = active_step_id_stack.pop() # Pop current step from stack | ||||||||||||||||||||||||||||||||
| step = steps[step_id] | ||||||||||||||||||||||||||||||||
| step.is_error = True | ||||||||||||||||||||||||||||||||
| step.output = data["output"] | ||||||||||||||||||||||||||||||||
| await step.update() | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| elif type == "claims_detected": | ||||||||||||||||||||||||||||||||
| # This logic is special and doesn't use the stack | ||||||||||||||||||||||||||||||||
| # It just adds claim-specific steps for later nesting | ||||||||||||||||||||||||||||||||
| main_pipeline_id = steps["Fact-Checking Pipeline"].id | ||||||||||||||||||||||||||||||||
| for i, claim in enumerate(data["claims"]): | ||||||||||||||||||||||||||||||||
| claim_id = f"claim_{i+1}" | ||||||||||||||||||||||||||||||||
| claim_step = cl.Step( | ||||||||||||||||||||||||||||||||
| name=f'Claim {i+1}: "{claim.text[:60]}..."', | ||||||||||||||||||||||||||||||||
| parent_id=main_pipeline_id, | ||||||||||||||||||||||||||||||||
| id=claim_id, | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| steps[claim_id] = claim_step | ||||||||||||||||||||||||||||||||
|
Comment on lines
+49
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Same collision risk for per-claim steps
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| await claim_step.send() | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # The main logic starts here | ||||||||||||||||||||||||||||||||
| await progress_callback(type="step_start", data={"title": "Fact-Checking Pipeline"}) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||
| verdicts = await pipeline.run(message.content, progress_callback=progress_callback, progress_msg=progress_msg) | ||||||||||||||||||||||||||||||||
| verdicts = await pipeline.run( | ||||||||||||||||||||||||||||||||
| message.content, progress_callback=progress_callback | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Debug logging to see what we got back | ||||||||||||||||||||||||||||||||
| logger.info(f"DEBUG: Received {len(verdicts) if verdicts else 0} verdicts") | ||||||||||||||||||||||||||||||||
| logger.info(f"DEBUG: Verdicts content: {verdicts}") | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if not verdicts: | ||||||||||||||||||||||||||||||||
| progress_msg.content = "No factual claims detected in your message." | ||||||||||||||||||||||||||||||||
| await progress_msg.update() | ||||||||||||||||||||||||||||||||
| await progress_callback( | ||||||||||||||||||||||||||||||||
| type="step_end", | ||||||||||||||||||||||||||||||||
| data={"output": "No factual claims were detected in your message."}, | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||
| # Format the final organized message | ||||||||||||||||||||||||||||||||
| response = "" | ||||||||||||||||||||||||||||||||
| for idx, (claim, evidence, verdict) in enumerate(verdicts): | ||||||||||||||||||||||||||||||||
| claim_text = getattr(claim, 'text', str(claim)) | ||||||||||||||||||||||||||||||||
| verdict_text = getattr(verdict, 'verdict', str(verdict)) | ||||||||||||||||||||||||||||||||
| confidence = getattr(verdict, 'confidence', 'N/A') | ||||||||||||||||||||||||||||||||
| explanation = getattr(verdict, 'explanation', 'N/A') | ||||||||||||||||||||||||||||||||
| sources = getattr(verdict, 'sources', []) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Format the final message and send it | ||||||||||||||||||||||||||||||||
| response = "## Fact-Checking Complete\nHere are the results:\n" | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| for idx, verdict_tuple in enumerate(verdicts): | ||||||||||||||||||||||||||||||||
| logger.info(f"DEBUG: Processing verdict {idx}: {verdict_tuple}") | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Handle different possible tuple structures | ||||||||||||||||||||||||||||||||
| if len(verdict_tuple) == 3: | ||||||||||||||||||||||||||||||||
| claim, evidence, verdict = verdict_tuple | ||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||
| logger.error(f"Unexpected verdict tuple structure: {verdict_tuple}") | ||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Safely extract attributes with fallbacks | ||||||||||||||||||||||||||||||||
| claim_text = ( | ||||||||||||||||||||||||||||||||
| getattr(claim, "text", str(claim)) if claim else "Unknown claim" | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| verdict_text = ( | ||||||||||||||||||||||||||||||||
| getattr(verdict, "verdict", str(verdict)) if verdict else "No verdict" | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| confidence = getattr(verdict, "confidence", "N/A") if verdict else "N/A" | ||||||||||||||||||||||||||||||||
| explanation = ( | ||||||||||||||||||||||||||||||||
| getattr(verdict, "explanation", "No explanation provided") | ||||||||||||||||||||||||||||||||
| if verdict | ||||||||||||||||||||||||||||||||
| else "N/A" | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| sources = getattr(verdict, "sources", []) if verdict else [] | ||||||||||||||||||||||||||||||||
| sources_str = "\n".join(sources) if sources else "No sources provided." | ||||||||||||||||||||||||||||||||
| # Evidence formatting | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if evidence: | ||||||||||||||||||||||||||||||||
| evidence_str = "\n".join([ | ||||||||||||||||||||||||||||||||
| f"- {getattr(ev, 'content', str(ev))} (Source: {getattr(ev, 'source', 'N/A')}, Stance: {getattr(ev, 'stance', 'N/A')}, Relevance: {getattr(ev, 'relevance', 'N/A')})" | ||||||||||||||||||||||||||||||||
| for ev in evidence | ||||||||||||||||||||||||||||||||
| ]) | ||||||||||||||||||||||||||||||||
| evidence_str = "\n".join( | ||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||
| f"- {getattr(ev, 'content', str(ev))} (Source: {getattr(ev, 'source', 'N/A')}, Stance: {getattr(ev, 'stance', 'N/A')}, Relevance: {getattr(ev, 'relevance', 'N/A')})" | ||||||||||||||||||||||||||||||||
| for ev in evidence | ||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||
| evidence_str = "No evidence found." | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| response += ( | ||||||||||||||||||||||||||||||||
| f"\n---\n**Claim {idx+1}:** {claim_text}\n" | ||||||||||||||||||||||||||||||||
| f"**Evidence:**\n{evidence_str}\n" | ||||||||||||||||||||||||||||||||
|
|
@@ -46,12 +121,26 @@ | |||||||||||||||||||||||||||||||
| f"**Explanation:** {explanation}\n" | ||||||||||||||||||||||||||||||||
| f"**Sources:**\n{sources_str}\n" | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| progress_msg.content = response | ||||||||||||||||||||||||||||||||
| await progress_msg.update() | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Close the main pipeline step and set its final output | ||||||||||||||||||||||||||||||||
| steps["Fact-Checking Pipeline"].output = response | ||||||||||||||||||||||||||||||||
| await steps["Fact-Checking Pipeline"].update() | ||||||||||||||||||||||||||||||||
| active_step_id_stack.pop() # Final pop for the main step | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
Comment on lines
+125
to
+129
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Main step never gets a formal You update the output and pop the stack, but the step remains in “running” state in the UI. Close it via the callback for consistency: - steps["Fact-Checking Pipeline"].output = response
- await steps["Fact-Checking Pipeline"].update()
- active_step_id_stack.pop() # Final pop for the main step
+ await progress_callback(
+ event_type="step_end",
+ data={"output": response},
+ )📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| # Send a final, separate message for easy viewing | ||||||||||||||||||||||||||||||||
| await cl.Message(content=response).send() | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||
| progress_msg.content = f"An error occurred during fact-checking: {str(e)}" | ||||||||||||||||||||||||||||||||
| await progress_msg.update() | ||||||||||||||||||||||||||||||||
| logger.error(f"An error occurred in the main pipeline: {e}", exc_info=True) | ||||||||||||||||||||||||||||||||
| # Check if there's an active step to mark as error | ||||||||||||||||||||||||||||||||
| if active_step_id_stack: | ||||||||||||||||||||||||||||||||
| await progress_callback( | ||||||||||||||||||||||||||||||||
| type="step_error", data={"output": f"An error occurred: {str(e)}"} | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| @cl.on_chat_start | ||||||||||||||||||||||||||||||||
| async def on_chat_start(): | ||||||||||||||||||||||||||||||||
| await cl.Message(content="👋 Welcome to VeriFact! The system is up and running. Type your claim or question to get started.").send() | ||||||||||||||||||||||||||||||||
| await cl.Message( | ||||||||||||||||||||||||||||||||
| content="👋 Welcome to VeriFact! The system is up and running. Type your claim or question to get started." | ||||||||||||||||||||||||||||||||
| ).send() | ||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,133 @@ | ||||||||||
| import pytest | ||||||||||
| from pydantic import ValidationError | ||||||||||
|
|
||||||||||
| # Adjust the import path based on your project structure. | ||||||||||
| # This assumes 'src' is in your PYTHONPATH or you're running pytest from the project root. | ||||||||||
| from verifact_agents.claim_detector import Claim, claim_detector_agent, PROMPT | ||||||||||
|
|
||||||||||
| # --- Fixtures --- | ||||||||||
| # Fixtures are a way to provide data or set up resources for your tests. | ||||||||||
|
|
||||||||||
| @pytest.fixture | ||||||||||
| def valid_claim_data() -> dict: | ||||||||||
| """Provides a dictionary with valid data for a Claim instance.""" | ||||||||||
| return { | ||||||||||
| "text": "The Earth is round.", | ||||||||||
| "normalized_text": "The Earth has a spherical shape.", | ||||||||||
| "check_worthiness_score": 0.9, | ||||||||||
| "specificity_score": 0.8, | ||||||||||
| "public_interest_score": 0.7, | ||||||||||
| "impact_score": 0.6, | ||||||||||
| "detection_confidence": 0.95, | ||||||||||
| "domain": "Science", | ||||||||||
| "entities": [{"text": "Earth", "type": "Planet"}], | ||||||||||
| "compound_claim_parts": None, | ||||||||||
| "rank": 1 | ||||||||||
| } | ||||||||||
|
|
||||||||||
| # --- Tests for the Claim Pydantic Model --- | ||||||||||
|
|
||||||||||
| def test_claim_creation_valid_data(valid_claim_data): | ||||||||||
| """Test that a Claim can be successfully created with valid data.""" | ||||||||||
| try: | ||||||||||
| claim = Claim(**valid_claim_data) | ||||||||||
| # Check a few key fields to ensure data is loaded correctly | ||||||||||
| assert claim.text == valid_claim_data["text"] | ||||||||||
| assert claim.normalized_text == valid_claim_data["normalized_text"] | ||||||||||
| assert claim.check_worthiness_score == valid_claim_data["check_worthiness_score"] | ||||||||||
| assert claim.rank == valid_claim_data["rank"] | ||||||||||
| assert claim.entities == valid_claim_data["entities"] | ||||||||||
| except ValidationError as e: | ||||||||||
| pytest.fail(f"Claim creation failed with valid data: {e}") | ||||||||||
|
|
||||||||||
| def test_claim_missing_required_field(valid_claim_data): | ||||||||||
| """Test that ValidationError is raised if a required field (e.g., 'text') is missing.""" | ||||||||||
| invalid_data = valid_claim_data.copy() | ||||||||||
| del invalid_data["text"] # 'text' is a required field | ||||||||||
|
|
||||||||||
| # pytest.raises is a context manager to check for expected exceptions | ||||||||||
| with pytest.raises(ValidationError) as excinfo: | ||||||||||
| Claim(**invalid_data) | ||||||||||
|
|
||||||||||
| # Optionally, you can inspect the exception details | ||||||||||
| assert "text" in str(excinfo.value).lower() # Check that the error message mentions 'text' | ||||||||||
| assert "field required" in str(excinfo.value).lower() | ||||||||||
|
|
||||||||||
| @pytest.mark.parametrize("score_field,invalid_value", [ | ||||||||||
| ("check_worthiness_score", -0.1), | ||||||||||
| ("check_worthiness_score", 1.1), | ||||||||||
| ("specificity_score", -0.5), | ||||||||||
| ("specificity_score", 1.5), | ||||||||||
|
|
||||||||||
|
|
||||||||||
| ("public_interest_score", -0.01), | ||||||||||
| ("public_interest_score", 2.0), | ||||||||||
| ("impact_score", -1.0), | ||||||||||
| ("impact_score", 1.0001), | ||||||||||
| ("detection_confidence", -0.2), | ||||||||||
| ("detection_confidence", 1.2), | ||||||||||
| ]) | ||||||||||
| def test_claim_score_out_of_range(valid_claim_data, score_field, invalid_value): | ||||||||||
| """Test that scores must be between 0.0 and 1.0.""" | ||||||||||
| invalid_data = valid_claim_data.copy() | ||||||||||
| invalid_data[score_field] = invalid_value | ||||||||||
|
|
||||||||||
| with pytest.raises(ValidationError) as excinfo: | ||||||||||
| Claim(**invalid_data) | ||||||||||
|
|
||||||||||
| # Check that the error message mentions the problematic field | ||||||||||
| assert score_field in str(excinfo.value) | ||||||||||
|
|
||||||||||
| def test_claim_default_values(valid_claim_data): | ||||||||||
| """Test default values for optional fields like 'entities' and 'compound_claim_parts'.""" | ||||||||||
| data = valid_claim_data.copy() | ||||||||||
| del data["entities"] # entities has default_factory=[] | ||||||||||
| del data["compound_claim_parts"] # compound_claim_parts has default=None | ||||||||||
| print("====>data:", data) | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove debug print statement. Debug print statements should not be committed to the test suite. - print("====>data:", data)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||
|
|
||||||||||
| claim = Claim(**data) | ||||||||||
|
|
||||||||||
| assert claim.entities == [] | ||||||||||
| assert claim.compound_claim_parts is None | ||||||||||
|
|
||||||||||
| def test_claim_extra_fields_forbidden(valid_claim_data): | ||||||||||
| """Test that extra fields are not allowed due to model_config = {'extra': 'forbid'}.""" | ||||||||||
| data_with_extra = valid_claim_data.copy() | ||||||||||
| data_with_extra["unexpected_field"] = "some_value" | ||||||||||
|
|
||||||||||
| with pytest.raises(ValidationError) as excinfo: | ||||||||||
| Claim(**data_with_extra) | ||||||||||
|
|
||||||||||
| assert "unexpected_field" in str(excinfo.value) | ||||||||||
| assert "extra inputs are not permitted" in str(excinfo.value).lower() | ||||||||||
|
|
||||||||||
| def test_claim_invalid_data_type_for_field(valid_claim_data): | ||||||||||
| """Test that providing an incorrect data type for a field raises ValidationError.""" | ||||||||||
| invalid_data = valid_claim_data.copy() | ||||||||||
| invalid_data["rank"] = "not-an-integer" # rank should be an int | ||||||||||
|
|
||||||||||
| with pytest.raises(ValidationError) as excinfo: | ||||||||||
| Claim(**invalid_data) | ||||||||||
| assert "rank" in str(excinfo.value) # Check that the error message mentions 'rank' | ||||||||||
|
|
||||||||||
| # --- Tests for the claim_detector_agent Instance --- | ||||||||||
|
|
||||||||||
| def test_claim_detector_agent_instantiation(): | ||||||||||
| """Test that the claim_detector_agent is instantiated and has basic properties.""" | ||||||||||
| assert claim_detector_agent is not None | ||||||||||
| assert claim_detector_agent.name == "ClaimDetector" | ||||||||||
|
|
||||||||||
| assert claim_detector_agent.output_type.__origin__ == list # Checks if it's a list type | ||||||||||
| assert claim_detector_agent.output_type.__args__[0] == Claim # Checks if the list contains Claim | ||||||||||
|
Comment on lines
+120
to
+121
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use proper type checking methods. Direct comparison with - assert claim_detector_agent.output_type.__origin__ == list # Checks if it's a list type
- assert claim_detector_agent.output_type.__args__[0] == Claim # Checks if the list contains Claim
+ assert claim_detector_agent.output_type.__origin__ is list # Checks if it's a list type
+ assert claim_detector_agent.output_type.__args__[0] is Claim # Checks if the list contains Claim📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.11.9)120-120: Use (E721) 🤖 Prompt for AI Agents |
||||||||||
|
|
||||||||||
| # Check if instructions are loaded (at least that it's not empty) | ||||||||||
| assert claim_detector_agent.instructions == PROMPT | ||||||||||
| assert PROMPT.strip() != "" # Ensure the PROMPT string itself is not empty | ||||||||||
|
|
||||||||||
| # Note: Testing the agent's actual processing (which calls an LLM) | ||||||||||
| # is an integration test and would require mocking os.getenv or the Agent's call method. | ||||||||||
| # For an MVP unit test, checking instantiation and configuration is a good start. | ||||||||||
|
|
||||||||||
| # You can add more tests here, for example: | ||||||||||
| # - Test specific constraints on 'entities' (e.g., must be list of dicts with 'text' and 'type') | ||||||||||
| # - Test 'compound_claim_parts' (e.g., must be list of strings if not None) | ||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Duplicate logger setup; central
setup_logging()is ignoredlogging.basicConfig()here overrides the richer configuration insrc/utils/logging/logging_config.py. Import and callsetup_logging()instead of re-initialising the root logger:🤖 Prompt for AI Agents