-
Notifications
You must be signed in to change notification settings - Fork 98
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
feat: googleai llm addition #152
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: royalpinto007 <[email protected]>
WalkthroughThis changeset integrates Google AI support across the backend director module. New enum members are added to expand language model options, and logic in the default LLM selector now accounts for Google AI based on environment variables. A dedicated module is introduced for handling Google AI functionalities, including chat completions and configurations. Additionally, agent parameter handling has been refined: parameters are filtered in the BaseAgent, the dubbing agent’s extra engine parameters are removed, and the UploadAgent now requires a Changes
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 1
🧹 Nitpick comments (2)
backend/director/llm/__init__.py (1)
16-16
: Usebool(...)
instead of a ternary operator
Static analysis suggests simplifying the logic by replacing"True if ... else False"
with a directbool(...)
.- googleai = True if os.getenv("GOOGLEAI_API_KEY") else False + googleai = bool(os.getenv("GOOGLEAI_API_KEY"))🧰 Tools
🪛 Ruff (0.8.2)
16-16: Use
bool(...)
instead ofTrue if ... else False
Replace with `bool(...)
(SIM210)
backend/director/llm/googleai.py (1)
59-61
: Raise exceptions with context
Within theImportError
block, consider raising the exception as:except ImportError as e: raise ImportError("Please install OpenAI python library.") from eto distinguish it from any secondary errors.
🧰 Tools
🪛 Ruff (0.8.2)
61-61: Within an
except
clause, raise exceptions withraise ... from err
orraise ... from None
to distinguish them from errors in exception handling(B904)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
backend/director/constants.py
(2 hunks)backend/director/llm/__init__.py
(2 hunks)backend/director/llm/googleai.py
(1 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
backend/director/llm/googleai.py
61-61: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
133-133: Do not use mutable data structures for argument defaults
Replace with None
; initialize within function
(B006)
backend/director/llm/__init__.py
16-16: Use bool(...)
instead of True if ... else False
Replace with `bool(...)
(SIM210)
🔇 Additional comments (14)
backend/director/constants.py (2)
22-22
: Addition ofGOOGLEAI
enum value
This new enumeration for Google AI is consistent with the existing pattern for LLM types.
31-31
: Addition ofGOOGLEAI_
environment prefix
This new environment prefix aligns well with the naming of other prefixes.backend/director/llm/__init__.py (2)
7-7
: New import for GoogleAI
No concerns with importingGoogleAI
.
24-25
: Conditional fallback for Google AI
The new branch for returningGoogleAI
is consistent with the handling for other LLM providers.backend/director/llm/googleai.py (10)
1-2
: Initial imports
No issues found with the added imports for JSON and Enum.
4-5
: Pydantic import statements
The imports for validators and settings appear correct.
7-12
: Imports from director modules
The references toRoleTypes
,BaseLLM
, and related classes look correct and consistent.
15-21
: Definition ofGoogleChatModel
Enum
Enumerating multiple Gemini chat models is clear and consistent with naming conventions.
23-49
:GoogleAIConfig
class implementation
The config class usesSettingsConfigDict
and an appropriate validator forapi_key
. This is a solid approach.
50-58
: Initialization ofGoogleAI
The constructor properly creates aGoogleAIConfig
when none is provided and initializes the base LLM.
63-65
: Verify use ofopenai.OpenAI(...)
for Google Gemini
The code currently constructsself.client
usingopenai.OpenAI(...)
, which is typically associated with OpenAI endpoints. Make sure this approach is truly compatible with Google Gemini, or confirm that you intend to leverage the OpenAI client library for interfacing with Google’s API.
67-115
:_format_messages
method
This method’s logic for handling system, assistant, tool, and user roles is well-structured and follows typical patterns for multi-turn conversation handling.
117-131
:_format_tools
method
The approach of enumerating functions for Gemini is clean and straightforward.
134-197
:chat_completions
method body
The method is logically clear: it formats parameters, handles the API request, parses the response, and captures metadata. Overall, it’s neatly organized.
Signed-off-by: royalpinto007 <[email protected]>
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.
Actionable comments posted: 1
🧹 Nitpick comments (4)
backend/director/llm/googleai.py (4)
54-65
: Improve exception handling when importing OpenAI.When catching the ImportError, you should use the
from
syntax to preserve the original traceback, which helps with debugging.try: import openai except ImportError: - raise ImportError("Please install OpenAI python library.") + raise ImportError("Please install OpenAI python library.") from None🧰 Tools
🪛 Ruff (0.8.2)
65-65: Within an
except
clause, raise exceptions withraise ... from err
orraise ... from None
to distinguish them from errors in exception handling(B904)
67-69
: Consider adding error handling for client initialization.The client initialization doesn't have any error handling. If there are issues with the API key or base URL, they'll only be discovered during the first API call.
-self.client = openai.OpenAI( - api_key=self.config.api_key, base_url=self.config.api_base -) +try: + self.client = openai.OpenAI( + api_key=self.config.api_key, base_url=self.config.api_base + ) +except Exception as e: + raise RuntimeError(f"Failed to initialize Google AI client: {e}") from e
139-140
: Update docstring to reflect using configured model.The docstring specifically mentions Gemini 1.5 Flash, but the code uses whatever model is configured in
self.config.chat_model
.-"""Get completions for chat using Gemini 1.5 Flash.""" +"""Get completions for chat using the configured Gemini model."""
141-147
: Redundant default values in parameter dictionary.The fallback values for temperature, max_tokens, and top_p are redundant since they already have defaults in the config class.
params = { "model": self.config.chat_model, "messages": self._format_messages(messages), - "temperature": self.config.temperature or 0.7, - "max_tokens": self.config.max_tokens or 4096, - "top_p": self.config.top_p or 1.0, + "temperature": self.config.temperature, + "max_tokens": self.config.max_tokens, + "top_p": self.config.top_p, }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
backend/director/llm/googleai.py
(1 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
backend/director/llm/googleai.py
65-65: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
137-137: Do not use mutable data structures for argument defaults
Replace with None
; initialize within function
(B006)
🔇 Additional comments (8)
backend/director/llm/googleai.py (8)
15-24
: Well-defined model enumeration.The
GoogleChatModel
enum provides a clear and comprehensive selection of Gemini models with appropriate naming conventions.
27-42
: Good configuration setup with appropriate defaults.The
GoogleAIConfig
class is well-structured with appropriate default values and extendsBaseLLMConfig
correctly. The use ofSettingsConfigDict
with the proper environment prefix is a good practice for configuration management.
44-51
: Effective validation with clear error message.The validator for the API key provides a helpful error message that includes instructions on how to set the environment variable correctly.
71-77
: Document why system messages are being removed.The code removes system messages from the input, but it's not clear why. If Gemini doesn't support system messages, this should be documented explicitly.
def _format_messages(self, messages: list): """Format the messages to the format that Google Gemini expects.""" formatted_messages = [] if messages and messages[0]["role"] == RoleTypes.system.value: + # Google Gemini doesn't support system messages, so we remove it messages = messages[1:]
136-138
: Avoid mutable default argument.Using
tools: list = []
can lead to subtle bugs. It's best practice to default toNone
and initialize internally.-def chat_completions(self, messages: list, tools: list = [], stop=None, response_format=None): +def chat_completions(self, messages: list, tools: list = None, stop=None, response_format=None): + if tools is None: + tools = []🧰 Tools
🪛 Ruff (0.8.2)
137-137: Do not use mutable data structures for argument defaults
Replace with
None
; initialize within function(B006)
170-184
: Handle potential KeyError in tool_calls extraction.The code assumes
tool_call.function.name
andtool_call.function.arguments
exist without checking, which could lead to errors if the response structure changes.tool_calls = ( [ { "id": tool_call.id, "tool": { - "name": tool_call.function.name, - "arguments": json.loads(tool_call.function.arguments), + "name": getattr(tool_call.function, "name", ""), + "arguments": json.loads(getattr(tool_call.function, "arguments", "{}")), }, "type": tool_call.type, } for tool_call in response.choices[0].message.tool_calls ] if response.choices and response.choices[0].message.tool_calls else [] )
186-189
: Good usage of getattr for safely accessing response attributes.Using
getattr
with a default value is a safe way to handle potentially missing attributes in the response.
190-198
: Well-structured response object creation.The
LLMResponse
creation is comprehensive and includes all necessary fields, with appropriate error handling for missing data.
try: | ||
response = self.client.chat.completions.create(**params) | ||
except Exception as e: | ||
print(f"Error: {e}") | ||
return LLMResponse(content=f"Error: {e}") | ||
|
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
Use proper error handling and logging instead of print statements.
Using print
for error logging isn't recommended in a library. Also, the error response should have an ERROR status.
try:
response = self.client.chat.completions.create(**params)
except Exception as e:
- print(f"Error: {e}")
- return LLMResponse(content=f"Error: {e}")
+ import logging
+ logging.error(f"Google AI chat completion error: {e}")
+ return LLMResponse(
+ content=f"Error: {e}",
+ status=LLMResponseStatus.ERROR
+ )
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
try: | |
response = self.client.chat.completions.create(**params) | |
except Exception as e: | |
print(f"Error: {e}") | |
return LLMResponse(content=f"Error: {e}") | |
try: | |
response = self.client.chat.completions.create(**params) | |
except Exception as e: | |
import logging | |
logging.error(f"Google AI chat completion error: {e}") | |
return LLMResponse( | |
content=f"Error: {e}", | |
status=LLMResponseStatus.ERROR | |
) |
Signed-off-by: royalpinto007 <[email protected]>
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.
Actionable comments posted: 0
🧹 Nitpick comments (3)
backend/director/agents/base.py (2)
51-56
: Be cautious about discarding optional parameters.
This filtering retains only the properties listed under"required"
. If your function has optional parameters you'd like to document or validate, they won't appear in this final schema.
58-62
: Return structure aligns with JSON schema, but consider adding more information.
The returned object properly sets"type":"object"
and includes minimal keys. If you want richer schema metadata (e.g.,"description"
, nested properties, or examples), it might help downstream integrations.backend/director/handler.py (1)
47-72
: Consider adding a comment explaining the agent removalsThe PR is adding Google AI integration, but it's not immediately clear why
UploadAgent
andDubbingAgent
are being disabled as part of this change. Adding a comment explaining this decision would improve code maintainability.# Register the agents here self.agents = [ ThumbnailAgent, SummarizeVideoAgent, DownloadAgent, PricingAgent, + # Temporarily disabled UploadAgent and DubbingAgent for Google AI integration + # due to [reason for disabling] # UploadAgent, SearchAgent, PromptClipAgent, ... # DubbingAgent, TranscriptionAgent, ... ]
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
backend/director/agents/base.py
(1 hunks)backend/director/handler.py
(2 hunks)
🔇 Additional comments (4)
backend/director/agents/base.py (2)
43-44
: Check if excludingargs
andkwargs
is intentional.
By popping these entries fromparameters["properties"]
, the schema omits them from validation. This is fine if your design never needs those parameters, but if there's any dynamic argument usage, consider preserving them.
46-49
: Ensureargs
andkwargs
removal fromrequired
matches desired usage.
Removing"args"
and"kwargs"
from the"required"
list is consistent with the approach above. Just confirm these parameters are never mandatory for your agent.backend/director/handler.py (2)
65-65
:❓ Verification inconclusive
Verify the impact of commenting out DubbingAgent
Commenting out the
DubbingAgent
removes dubbing functionality from theChatHandler
. This may affect users who rely on this feature.Please confirm if this is an intentional change related to the Google AI integration. If the agent is incompatible with the new Google AI implementation, this should be documented.
🏁 Script executed:
#!/bin/bash # Check if DubbingAgent is used elsewhere in the codebase echo "Checking references to DubbingAgent in the codebase..." rg "DubbingAgent" --type py # Check if there are any direct API calls or frontend code that might expect this agent echo "Checking API routes or endpoints that might use DubbingAgent..." rg -A 5 -B 5 "dubbing.*agent" --type pyLength of output: 524
Review Note: Confirm Intentional Removal of Dubbing Functionality
It appears that the
ChatHandler
now has theDubbingAgent
instantiation commented out (line 65 inbackend/director/handler.py
). Our search confirms that while theDubbingAgent
class is still defined inbackend/director/agents/dubbing.py
and imported inChatHandler
, there are no other references or API routes relying on it. This indicates that the dubbing functionality is effectively disabled.Please confirm whether this change is intentional as part of the Google AI integration. If the removal is deliberate, ensure that the decision is documented so that users relying on the dubbing feature are aware of the change.
52-52
:❓ Verification inconclusive
Verify the impact of commenting out UploadAgent
Commenting out the
UploadAgent
means this functionality will no longer be available through theChatHandler
. This might impact existing functionality if any part of the system relies on upload capabilities via the chat interface.Consider whether this change is intentional as part of the Google AI integration or if it's an oversight. If intentional, please document why this agent is being disabled.
🏁 Script executed:
#!/bin/bash # Check if UploadAgent is used elsewhere in the codebase echo "Checking references to UploadAgent in the codebase..." rg "UploadAgent" --type py # Check if there are any direct API calls or frontend code that might expect this agent echo "Checking API routes or endpoints that might use UploadAgent..." rg -A 5 -B 5 "upload.*agent" --type pyLength of output: 1516
Impact of Removing UploadAgent from ChatHandler
Our investigation confirms that while the
UploadAgent
remains defined inbackend/director/agents/upload.py
and its import is still present inbackend/director/handler.py
, the actual usage in the ChatHandler has been commented out. Additionally, the fallback logic inbackend/director/core/reasoning.py
explicitly references the upload agent (to generate a video_id when needed).
- Location Check:
backend/director/agents/upload.py
: Contains theUploadAgent
class.backend/director/handler.py
: The line invokingUploadAgent
is commented out, although the import still exists.backend/director/core/reasoning.py
: The fallback behavior relies on the upload agent.If disabling the upload functionality via the ChatHandler is part of the intended Google AI integration, please document the rationale. Otherwise, if this was inadvertent, you may need to restore its functionality to support the fallback process.
Signed-off-by: royalpinto007 <[email protected]>
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.
Actionable comments posted: 1
🧹 Nitpick comments (1)
backend/director/agents/upload.py (1)
18-45
: Consider removing commented-out code after successful transition to dynamic parameters.The code has been changed to use a dynamic parameter retrieval method (
self.get_parameters()
) instead of a static definition. The commented-out code could be removed to improve maintenance and readability if the dynamic approach is confirmed to work properly.-# UPLOAD_AGENT_PARAMETERS = { -# "type": "object", -# "properties": { -# "source": { -# "type": "string", -# "description": "URL or local path to upload the content", -# }, -# "source_type": { -# "type": "string", -# "description": "Type of given source.", -# "enum": ["url", "local_file"], -# }, -# "name": { -# "type": "string", -# "description": "Name of the content to upload, optional parameter", -# }, -# "media_type": { -# "type": "string", -# "enum": ["video", "audio", "image"], -# "description": "Type of media to upload, default is video", -# }, -# "collection_id": { -# "type": "string", -# "description": "Collection ID to upload the content", -# }, -# }, -# "required": ["url", "media_type", "collection_id"], -# }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
backend/director/agents/dubbing.py
(1 hunks)backend/director/agents/upload.py
(2 hunks)
🔇 Additional comments (1)
backend/director/agents/upload.py (1)
57-57
:✅ Verification successful
Verify parameter structure consistency with get_parameters() method.
Ensure that the
get_parameters()
method returns a structure consistent with the previous static definition, including all required fields and proper type definitions.
🏁 Script executed:
#!/bin/bash # Check the implementation of get_parameters() in BaseAgent rg -A 10 "def get_parameters" --type pyLength of output: 958
Parameter Structure Verified – No Action Required
The implementation ofget_parameters()
inBaseAgent
now dynamically infers the JSON schema from the associated run function. The method retrieves the parameters viafunction_inferrer.to_json_schema()
, raises an exception if parameters are missing, and explicitly removes the unwanted"args"
property from the schema. This strategy appears to maintain consistency with the previously static parameter definition by ensuring that the required fields and type definitions are derived at runtime.
- Action: Confirm via integration tests that the dynamically generated JSON schema (including keys like
"properties"
,"required"
, and any type definitions) matches the expected structure for all agents (e.g., inupload.py
at line 57).
Signed-off-by: royalpinto007 <[email protected]>
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
backend/director/agents/upload.py (1)
172-184
: Good validation, but note potential redundancy.The input validation here is thorough and appropriate. However, there appears to be some redundancy in the code - the
source_type
validation at lines 179-184 overlaps with the validation logic at lines 197-202.Consider removing the redundant validation at lines 197-202 since you're now handling it earlier in the method. The error case at line 197 should never be reached with the new validation in place.
elif source_type == "url": playlist_info = self._get_yt_playlist_videos(source) if playlist_info: self.output_message.actions.append("YouTube Playlist detected") self.output_message.push_update() return self._upload_yt_playlist(playlist_info, media_type) return self._upload(source, source_type, media_type, name) - else: - error_message = f"Invalid source type {source_type}" - logger.error(error_message) - return AgentResponse( - status=AgentStatus.ERROR, message=error_message, data={} - )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
backend/director/agents/dubbing.py
(0 hunks)backend/director/agents/upload.py
(3 hunks)
💤 Files with no reviewable changes (1)
- backend/director/agents/dubbing.py
🔇 Additional comments (2)
backend/director/agents/upload.py (2)
44-44
: Good parameter requirement update.Updating the required parameters to only include
media_type
andcollection_id
makes sense. This change aligns with the more flexible approach wheresource
can be provided as either a URL or local file path, and is validated separately.
63-68
: Good input validation implementation.Adding validation for the
source
parameter is a good defensive programming practice. This ensures that the upload operation receives valid input data and fails gracefully with a clear error message when requirements aren't met.
Signed-off-by: royalpinto007 <[email protected]>
Summary by CodeRabbit