Skip to content
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

Fix nested pydantic model issue #1905

Merged
merged 11 commits into from
Jan 16, 2025
Merged

Fix nested pydantic model issue #1905

merged 11 commits into from
Jan 16, 2025

Conversation

bhancockio
Copy link
Collaborator

@bhancockio bhancockio commented Jan 15, 2025

Explanation and proof that PR works: https://www.loom.com/share/5a338203b1c24030b702dd5fc18b84f7?sid=f70da264-f042-485a-81c1-8f42d60562ca

closes #911 - 99% of the credit goes to @inchoate! I need to add a few more tests and fix a few upstream issues.

@joaomdmoura
Copy link
Collaborator

Disclaimer: This review was made by a crew of AI Agents.

Code Review Comment for PR #1905 - Fix Nested Pydantic Model Issue

Overview

This pull request addresses the handling of nested Pydantic models and improves the conversion utilities' error handling and support for complex data structures. Overall, the changes are commendable, enhancing the system's resilience.

Key Code Improvements

1. converter.py

  • Issue: Presence of debug print statements in production code.

  • Recommendation: Replace these with a proper logging mechanism to prevent clutter in the production environment.

    # Remove debug print statements
    def _create_instructor(self):
        from crewai.utilities import InternalInstructor
        return InternalInstructor(
            llm=self.llm,
            model=self.model,
            content=self.text,
        )
  • Issue: Inconsistent error handling patterns.

  • Recommendation: Implement uniform error handling practices.

    def to_pydantic(self, current_attempt=1):
        try:
            if self.llm.supports_function_calling():
                return self._create_instructor().to_pydantic()
            response = self.llm.call([
                {"role": "system", "content": self.instructions},
                {"role": "user", "content": self.text},
            ])
            return self.model.model_validate_json(response)
        except (ValidationError, Exception) as e:
            if current_attempt < self.max_attempts:
                return self.to_pydantic(current_attempt + 1)
            raise ConverterError(f"Failed to convert text: {str(e)}")

2. internal_instructor.py

  • Issue: Unnecessary warning suppression and redundant parameter.
  • Recommendation: Clean up methods and remove redundancies.
    def set_instructor(self):
        if self.agent and not self.llm:
            self.llm = self.agent.function_calling_llm or self.agent.llm
        import instructor
        from litellm import completion
        self._client = instructor.from_litellm(completion)

3. pydantic_schema_parser.py

  • Issue: Complex nested type handling could be simplified.
  • Recommendation: Streamline type processing to improve readability and maintainability.
    def _get_field_type(self, field, depth: int) -> str:
        field_type = field.annotation
        origin = get_origin(field_type)
        
        type_handlers = {
            list: lambda: self._format_list_type(get_args(field_type)[0], depth),
            Dict: lambda: self._format_dict_type(*get_args(field_type)),
        }        
        if origin in type_handlers:
            return type_handlers[origin]()
        
        return field_type.__name__

Historical Context

Recent changes in these files suggested a conscious effort to enhance error handling and type management. Analyzing related PRs that focused on handling Pydantic models may provide insights into the evolution of practices within this codebase. For instance, observing past discussions about error handling could enrich your understanding of current approaches.

Testing and Coverage

While the addition of considerate test coverage substantially improves confidence, consider integrating parameterized tests for broader scenarios. Example:

@pytest.mark.parametrize("model_config", [
    (SimpleModel, {"name": "Test", "age": 30}),
])

General Recommendations

  1. Logging Implementation: Implement structured logging over print statements for better tracking of issues.
  2. Error Handling: Enhance specific exception types and error messages for clearer diagnostics.
  3. Code Organization: Rationalize large functions and move utility functions into distinct modules for increased maintainability.
  4. Documentation: Include comprehensive docstrings for new methods, outlining functionality and expected edge cases.

Security Implications

  1. Validate all input and ensure limits are set to mitigate DOS attacks.
  2. Sanitize error messages to avoid leaking sensitive information.

Conclusion

The enhancements proposed in this PR significantly bolster the Pydantic model handling capabilities and strengthen test coverage, assuring greater reliability. However, attention to logging, error handling uniformity, and some architectural decisions remains essential before merging this pull request. Thus, I recommend merging after the outlined adjustments are addressed.

@lorenzejay lorenzejay self-requested a review January 15, 2025 23:30
Copy link
Collaborator

@lorenzejay lorenzejay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

works for me. just those type issues locally potentially!

@lorenzejay lorenzejay self-requested a review January 16, 2025 15:58
@@ -25,7 +25,7 @@ class OutputConverter(BaseModel, ABC):
llm: Any = Field(description="The language model to be used to convert the text.")
model: Any = Field(description="The model to be used to convert the text.")
instructions: str = Field(description="Conversion instructions to the LLM.")
max_attempts: Optional[int] = Field(
max_attempts: int = Field(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice fix !

@bhancockio bhancockio merged commit b5779dc into main Jan 16, 2025
4 checks passed
@bhancockio bhancockio deleted the bugfix/pydantic-fix-and-docs branch January 16, 2025 16:29
recursiveAF pushed a commit to recursiveAF/crewAI that referenced this pull request Jan 25, 2025
* Fix nested pydantic model issue

* fix failing tests

* add in vcr

* cleanup

* drop prints

* Fix vcr issues

* added new recordings

* trying to fix vcr

* add in fix from lorenze.
devin-ai-integration bot pushed a commit that referenced this pull request Feb 9, 2025
* Fix nested pydantic model issue

* fix failing tests

* add in vcr

* cleanup

* drop prints

* Fix vcr issues

* added new recordings

* trying to fix vcr

* add in fix from lorenze.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants