feat: add OCI Generative AI provider — basic text completion#4959
feat: add OCI Generative AI provider — basic text completion#4959fede-kamel wants to merge 6 commits into
Conversation
|
@greysonlalonde Hey! Following up on your feedback from #4885 — I split the original PR into smaller, scoped pieces. This is the first one: just the basic text completion provider for OCI GenAI (no streaming, no tools, no structured output, no multimodal, no embeddings). I couldn't trim this one further — it's the minimal foundation (provider class + shared auth + registration) plus tests. The source code is ~600 lines and the rest is test fixtures/tests. Each follow-up PR will layer on one capability at a time. Also, per the community tools guide you shared — the OCI tools (InvokeAgent, KnowledgeBase, ObjectStorage) will go into a standalone PyPI package ( Would appreciate a review whenever you get a chance. Thanks! |
105d7dd to
e6b52b5
Compare
Add streaming text completion via OCI SSE events: - stream=True in call() routes to _stream_call_impl with chunk events - iter_stream() yields raw text chunks (sync generator) - astream() wraps iter_stream via thread+queue for async callers - _stream_chat_events holds client lock for full stream duration - SSE event parsing handles both string and mapping payloads Tested live against meta.llama-3.3-70b-instruct, cohere.command-r-plus-08-2024, google.gemini-2.5-flash, and openai.gpt-5.2-chat-latest. Depends on: crewAIInc#4959 Tracking issue: crewAIInc#4944
Add streaming text completion via OCI SSE events: - stream=True in call() routes to _stream_call_impl with chunk events - iter_stream() yields raw text chunks (sync generator) - astream() wraps iter_stream via thread+queue for async callers - _stream_chat_events holds client lock for full stream duration - SSE event parsing handles both string and mapping payloads Tested live against meta.llama-3.3-70b-instruct, cohere.command-r-plus-08-2024, google.gemini-2.5-flash, and openai.gpt-5.2-chat-latest. Depends on: crewAIInc#4959 Tracking issue: crewAIInc#4944
Add native function calling for generic and Cohere model families: - _format_tools converts CrewAI tool specs to OCI SDK format - _extract_tool_calls normalizes responses back to CrewAI shape - _handle_tool_calls executes tools and recurses until model finishes - Cohere tool message handling with trailing tool results - Tool choice control (auto/none/required/function) - Passthrough parameter filtering via SDK introspection - Streaming tool call accumulation from SSE fragments - supports_function_calling() returns True Tested live against meta.llama-3.3-70b-instruct with raw tool call return and recursive tool execution. Depends on: crewAIInc#4961 (streaming), crewAIInc#4959 (basic text) Tracking issue: crewAIInc#4944
Add streaming text completion via OCI SSE events: - stream=True in call() routes to _stream_call_impl with chunk events - iter_stream() yields raw text chunks (sync generator) - astream() wraps iter_stream via thread+queue for async callers - _stream_chat_events holds client lock for full stream duration - SSE event parsing handles both string and mapping payloads Tested live against meta.llama-3.3-70b-instruct, cohere.command-r-plus-08-2024, google.gemini-2.5-flash, and openai.gpt-5.2-chat-latest. Depends on: crewAIInc#4959 Tracking issue: crewAIInc#4944
Add native function calling for generic and Cohere model families: - _format_tools converts CrewAI tool specs to OCI SDK format - _extract_tool_calls normalizes responses back to CrewAI shape - _handle_tool_calls executes tools and recurses until model finishes - Cohere tool message handling with trailing tool results - Tool choice control (auto/none/required/function) - Passthrough parameter filtering via SDK introspection - Streaming tool call accumulation from SSE fragments - supports_function_calling() returns True Tested live against meta.llama-3.3-70b-instruct with raw tool call return and recursive tool execution. Depends on: crewAIInc#4961 (streaming), crewAIInc#4959 (basic text) Tracking issue: crewAIInc#4944
Add response_model (Pydantic) support for structured output: - _build_response_format converts Pydantic schema to OCI JsonSchemaResponseFormat (generic) or CohereResponseJsonFormat - _parse_structured_response validates and returns typed models - response_model threaded through call, _call_impl, _stream_call_impl, and _handle_tool_calls for full coverage - Handles JSON in markdown fences via base class _validate_structured_output Tested live against meta.llama-3.3-70b-instruct and google.gemini-2.5-flash. Depends on: crewAIInc#4962 (tool calling), crewAIInc#4961 (streaming), crewAIInc#4959 (basic text) Tracking issue: crewAIInc#4944
Add streaming text completion via OCI SSE events: - stream=True in call() routes to _stream_call_impl with chunk events - iter_stream() yields raw text chunks (sync generator) - astream() wraps iter_stream via thread+queue for async callers - _stream_chat_events holds client lock for full stream duration - SSE event parsing handles both string and mapping payloads Tested live against meta.llama-3.3-70b-instruct, cohere.command-r-plus-08-2024, google.gemini-2.5-flash, and openai.gpt-5.2-chat-latest. Depends on: crewAIInc#4959 Tracking issue: crewAIInc#4944
Add native function calling for generic and Cohere model families: - _format_tools converts CrewAI tool specs to OCI SDK format - _extract_tool_calls normalizes responses back to CrewAI shape - _handle_tool_calls executes tools and recurses until model finishes - Cohere tool message handling with trailing tool results - Tool choice control (auto/none/required/function) - Passthrough parameter filtering via SDK introspection - Streaming tool call accumulation from SSE fragments - supports_function_calling() returns True Tested live against meta.llama-3.3-70b-instruct with raw tool call return and recursive tool execution. Depends on: crewAIInc#4961 (streaming), crewAIInc#4959 (basic text) Tracking issue: crewAIInc#4944
Add response_model (Pydantic) support for structured output: - _build_response_format converts Pydantic schema to OCI JsonSchemaResponseFormat (generic) or CohereResponseJsonFormat - _parse_structured_response validates and returns typed models - response_model threaded through call, _call_impl, _stream_call_impl, and _handle_tool_calls for full coverage - Handles JSON in markdown fences via base class _validate_structured_output Tested live against meta.llama-3.3-70b-instruct and google.gemini-2.5-flash. Depends on: crewAIInc#4962 (tool calling), crewAIInc#4961 (streaming), crewAIInc#4959 (basic text) Tracking issue: crewAIInc#4944
Add multimodal content handling for generic model families: - vision.py: model lists, data URI helpers, image encoding utilities - _build_generic_content handles image_url, document_url, video_url, audio_url content types mapped to OCI SDK content objects - _message_has_multimodal_content detects non-text payloads - Cohere models reject multimodal with clear error message - supports_multimodal() returns True Depends on: crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959 Tracking issue: crewAIInc#4944
0cfe8ca to
d15e5d4
Compare
- OCICompletion(BaseLLM): sync call() and async acall() for generic (Meta, Google, OpenAI, xAI) and Cohere model families - Shared OCI auth utilities (utilities/oci.py): API key, security token, instance principal, and resource principal auth - Provider routing in llm.py: oci/ prefix and OCI model-id patterns - oci registered as optional dependency (crewai[oci]) - Configurable timeout via DEFAULT_OCI_TIMEOUT constant - Cohere and generic request/response paths fully separated Tracking issue: crewAIInc#4944 Part 1 of series: crewAIInc#4959 → crewAIInc#4961 → crewAIInc#4962 → crewAIInc#4963 → crewAIInc#4964 → crewAIInc#4966 → crewAIInc#4982
|
@greysonlalonde @lorenzejay — bump for review. Status
Bug fixed in the latest commit (
|
Add streaming text completion via OCI SSE events: - stream=True in call() routes to _stream_call_impl with chunk events - iter_stream() yields raw text chunks (sync generator) - astream() wraps iter_stream via thread+queue for async callers - _stream_chat_events holds client lock for full stream duration - SSE event parsing handles both string and mapping payloads Tested live against meta.llama-3.3-70b-instruct, cohere.command-r-plus-08-2024, google.gemini-2.5-flash, and openai.gpt-5.2-chat-latest. Depends on: crewAIInc#4959 Tracking issue: crewAIInc#4944
Add streaming text completion via OCI SSE events: - stream=True in call() routes to _stream_call_impl with chunk events - iter_stream() yields raw text chunks (sync generator) - astream() wraps iter_stream via thread+queue for async callers - _stream_chat_events holds client lock for full stream duration - SSE event parsing handles both string and mapping payloads Tested live against meta.llama-3.3-70b-instruct, cohere.command-r-plus-08-2024, google.gemini-2.5-flash, and openai.gpt-5.2-chat-latest. Depends on: crewAIInc#4959 Tracking issue: crewAIInc#4944
Add native function calling for generic and Cohere model families: - _format_tools converts CrewAI tool specs to OCI SDK format - _extract_tool_calls normalizes responses back to CrewAI shape - _handle_tool_calls executes tools and recurses until model finishes - Cohere tool message handling with trailing tool results - Tool choice control (auto/none/required/function) - Passthrough parameter filtering via SDK introspection - Streaming tool call accumulation from SSE fragments - supports_function_calling() returns True Tested live against meta.llama-3.3-70b-instruct with raw tool call return and recursive tool execution. Depends on: crewAIInc#4961 (streaming), crewAIInc#4959 (basic text) Tracking issue: crewAIInc#4944
Add streaming text completion via OCI SSE events: - stream=True in call() routes to _stream_call_impl with chunk events - iter_stream() yields raw text chunks (sync generator) - astream() wraps iter_stream via thread+queue for async callers - _stream_chat_events holds client lock for full stream duration - SSE event parsing handles both string and mapping payloads Tested live against meta.llama-3.3-70b-instruct, cohere.command-r-plus-08-2024, google.gemini-2.5-flash, and openai.gpt-5.2-chat-latest. Depends on: crewAIInc#4959 Tracking issue: crewAIInc#4944
Add native function calling for generic and Cohere model families: - _format_tools converts CrewAI tool specs to OCI SDK format - _extract_tool_calls normalizes responses back to CrewAI shape - _handle_tool_calls executes tools and recurses until model finishes - Cohere tool message handling with trailing tool results - Tool choice control (auto/none/required/function) - Passthrough parameter filtering via SDK introspection - Streaming tool call accumulation from SSE fragments - supports_function_calling() returns True Tested live against meta.llama-3.3-70b-instruct with raw tool call return and recursive tool execution. Depends on: crewAIInc#4961 (streaming), crewAIInc#4959 (basic text) Tracking issue: crewAIInc#4944
Add response_model (Pydantic) support for structured output: - _build_response_format converts Pydantic schema to OCI JsonSchemaResponseFormat (generic) or CohereResponseJsonFormat - _parse_structured_response validates and returns typed models - response_model threaded through call, _call_impl, _stream_call_impl, and _handle_tool_calls for full coverage - Handles JSON in markdown fences via base class _validate_structured_output Tested live against meta.llama-3.3-70b-instruct and google.gemini-2.5-flash. Depends on: crewAIInc#4962 (tool calling), crewAIInc#4961 (streaming), crewAIInc#4959 (basic text) Tracking issue: crewAIInc#4944
Add multimodal content handling for generic model families: - vision.py: model lists, data URI helpers, image encoding utilities - _build_generic_content handles image_url, document_url, video_url, audio_url content types mapped to OCI SDK content objects - _message_has_multimodal_content detects non-text payloads - Cohere models reject multimodal with clear error message - supports_multimodal() returns True Depends on: crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959 Tracking issue: crewAIInc#4944
Add streaming text completion via OCI SSE events: - stream=True in call() routes to _stream_call_impl with chunk events - iter_stream() yields raw text chunks (sync generator) - astream() wraps iter_stream via thread+queue for async callers - _stream_chat_events holds client lock for full stream duration - SSE event parsing handles both string and mapping payloads Tested live against meta.llama-3.3-70b-instruct, cohere.command-r-plus-08-2024, google.gemini-2.5-flash, and openai.gpt-5.2-chat-latest. Depends on: crewAIInc#4959 Tracking issue: crewAIInc#4944
Add native function calling for generic and Cohere model families: - _format_tools converts CrewAI tool specs to OCI SDK format - _extract_tool_calls normalizes responses back to CrewAI shape - _handle_tool_calls executes tools and recurses until model finishes - Cohere tool message handling with trailing tool results - Tool choice control (auto/none/required/function) - Passthrough parameter filtering via SDK introspection - Streaming tool call accumulation from SSE fragments - supports_function_calling() returns True Tested live against meta.llama-3.3-70b-instruct with raw tool call return and recursive tool execution. Depends on: crewAIInc#4961 (streaming), crewAIInc#4959 (basic text) Tracking issue: crewAIInc#4944
Add response_model (Pydantic) support for structured output: - _build_response_format converts Pydantic schema to OCI JsonSchemaResponseFormat (generic) or CohereResponseJsonFormat - _parse_structured_response validates and returns typed models - response_model threaded through call, _call_impl, _stream_call_impl, and _handle_tool_calls for full coverage - Handles JSON in markdown fences via base class _validate_structured_output Tested live against meta.llama-3.3-70b-instruct and google.gemini-2.5-flash. Depends on: crewAIInc#4962 (tool calling), crewAIInc#4961 (streaming), crewAIInc#4959 (basic text) Tracking issue: crewAIInc#4944
Add multimodal content handling for generic model families: - vision.py: model lists, data URI helpers, image encoding utilities - _build_generic_content handles image_url, document_url, video_url, audio_url content types mapped to OCI SDK content objects - _message_has_multimodal_content detects non-text payloads - Cohere models reject multimodal with clear error message - supports_multimodal() returns True Depends on: crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959 Tracking issue: crewAIInc#4944
Replace asyncio.to_thread wrappers with true async I/O using aiohttp for acall() and astream(). The OCI SDK is sync-only, so we bypass it for HTTP and use its signer for request authentication directly. - oci_async.py: OCIAsyncClient with aiohttp, OCI request signing, native SSE parsing, connection pooling - acall(): true async chat completion (no thread pool) - astream(): true async SSE streaming (no thread+queue bridge) - Graceful fallback to asyncio.to_thread when aiohttp unavailable or client is mocked (unit tests) - aiohttp + certifi added to crewai[oci] optional deps Temporary measure until OCI SDK ships native async support. Tested live: acall, astream, and concurrent acall against meta.llama-3.3-70b-instruct with API_KEY auth. Depends on: crewAIInc#4966, crewAIInc#4964, crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959 Tracking issue: crewAIInc#4944
Add OCI embedding support integrated with CrewAI's RAG pipeline: - OCIEmbeddingFunction: ChromaDB-compatible embedding callable with batching, config serialization, image embedding support - OCIProvider: Pydantic-based provider with alias validation for env vars and config keys - Factory registration in embeddings/factory.py + types.py - Supports text and image embeddings, output dimensions, custom endpoints, all 4 OCI auth modes Tested live against cohere.embed-english-v3.0 with API_KEY auth. Depends on: crewAIInc#4964, crewAIInc#4963, crewAIInc#4962, crewAIInc#4961, crewAIInc#4959 Tracking issue: crewAIInc#4944
- OCICompletion(BaseLLM): sync call() and async acall() for generic (Meta, Google, OpenAI, xAI) and Cohere model families - Shared OCI auth utilities (utilities/oci.py): API key, security token, instance principal, and resource principal auth - Provider routing in llm.py: oci/ prefix and OCI model-id patterns - oci registered as optional dependency (crewai[oci]) - Configurable timeout via DEFAULT_OCI_TIMEOUT constant - Cohere and generic request/response paths fully separated Tracking issue: crewAIInc#4944 Part 1 of series: crewAIInc#4959 → crewAIInc#4961 → crewAIInc#4962 → crewAIInc#4963 → crewAIInc#4964 → crewAIInc#4966 → crewAIInc#4982
3fda605 to
986bb3c
Compare
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThis PR adds OCI Generative AI as a native LLM provider: optional dependency, LLM routing updates, OCICompletion implementation with request/response handling and model-specific quirks, OCI client utilities for multiple auth modes, and unit + live integration tests. ChangesOCI Generative AI Provider
🎯 3 (Moderate) | ⏱️ ~25 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/crewai/tests/llms/oci/conftest.py`:
- Around line 170-175: The current pattern uses if os.getenv("VAR"):
config["key"] = os.getenv("VAR", "default") which makes the default unreachable;
change to capture the env value once and use it (e.g., value =
os.getenv("OCI_AUTH_TYPE"); if value: config["auth_type"] = value) for each of
OCI_AUTH_TYPE, OCI_AUTH_PROFILE, and OCI_AUTH_FILE_LOCATION (referencing config
and os.getenv) so you don't call os.getenv twice and eliminate the dead default
arguments.
In `@lib/crewai/tests/llms/oci/test_oci_integration_basic.py`:
- Line 7: Update the run instruction that points to
tests/llms/oci/test_oci_integration_basic.py so it uses the correct repository
path (lib/crewai/tests/llms/oci/test_oci_integration_basic.py); change the
command line shown (uv run pytest ...) to reference the full correct path or to
run pytest from repo root (e.g., uv run pytest
lib/crewai/tests/llms/oci/test_oci_integration_basic.py -v) so contributors can
execute the test as written.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: d79e554b-3f40-4adc-a0bb-6de0c6eff7e9
📒 Files selected for processing (9)
lib/crewai/pyproject.tomllib/crewai/src/crewai/llm.pylib/crewai/src/crewai/llms/providers/oci/__init__.pylib/crewai/src/crewai/llms/providers/oci/completion.pylib/crewai/src/crewai/utilities/oci.pylib/crewai/tests/llms/oci/__init__.pylib/crewai/tests/llms/oci/conftest.pylib/crewai/tests/llms/oci/test_oci.pylib/crewai/tests/llms/oci/test_oci_integration_basic.py
| if os.getenv("OCI_AUTH_TYPE"): | ||
| config["auth_type"] = os.getenv("OCI_AUTH_TYPE", "API_KEY") | ||
| if os.getenv("OCI_AUTH_PROFILE"): | ||
| config["auth_profile"] = os.getenv("OCI_AUTH_PROFILE", "DEFAULT") | ||
| if os.getenv("OCI_AUTH_FILE_LOCATION"): | ||
| config["auth_file_location"] = os.getenv("OCI_AUTH_FILE_LOCATION", "~/.oci/config") |
There was a problem hiding this comment.
Remove redundant os.getenv() calls; defaults are unreachable dead code.
The pattern if os.getenv(X): followed by os.getenv(X, default) means the default parameter can never be used—you've already verified the variable is truthy. The defaults "API_KEY", "DEFAULT", and "~/.oci/config" on lines 171, 173, and 175 are dead code.
♻️ Simplify by removing the redundant second call
- if os.getenv("OCI_AUTH_TYPE"):
- config["auth_type"] = os.getenv("OCI_AUTH_TYPE", "API_KEY")
- if os.getenv("OCI_AUTH_PROFILE"):
- config["auth_profile"] = os.getenv("OCI_AUTH_PROFILE", "DEFAULT")
- if os.getenv("OCI_AUTH_FILE_LOCATION"):
- config["auth_file_location"] = os.getenv("OCI_AUTH_FILE_LOCATION", "~/.oci/config")
+ if auth_type := os.getenv("OCI_AUTH_TYPE"):
+ config["auth_type"] = auth_type
+ if auth_profile := os.getenv("OCI_AUTH_PROFILE"):
+ config["auth_profile"] = auth_profile
+ if auth_file := os.getenv("OCI_AUTH_FILE_LOCATION"):
+ config["auth_file_location"] = auth_file🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/crewai/tests/llms/oci/conftest.py` around lines 170 - 175, The current
pattern uses if os.getenv("VAR"): config["key"] = os.getenv("VAR", "default")
which makes the default unreachable; change to capture the env value once and
use it (e.g., value = os.getenv("OCI_AUTH_TYPE"); if value: config["auth_type"]
= value) for each of OCI_AUTH_TYPE, OCI_AUTH_PROFILE, and OCI_AUTH_FILE_LOCATION
(referencing config and os.getenv) so you don't call os.getenv twice and
eliminate the dead default arguments.
| OCI_AUTH_TYPE=API_KEY OCI_AUTH_PROFILE=API_KEY_AUTH \ | ||
| OCI_COMPARTMENT_ID=<compartment> OCI_REGION=us-chicago-1 \ | ||
| OCI_TEST_MODELS="meta.llama-3.3-70b-instruct,cohere.command-r-plus-08-2024,google.gemini-2.5-flash" \ | ||
| uv run pytest tests/llms/oci/test_oci_integration_basic.py -v |
There was a problem hiding this comment.
Fix the pytest path in the run instructions.
Line 7 points to tests/llms/oci/test_oci_integration_basic.py, but this file lives under lib/crewai/tests/..., so the command is likely wrong for contributors copying it verbatim.
Suggested diff
- uv run pytest tests/llms/oci/test_oci_integration_basic.py -v
+ uv run pytest lib/crewai/tests/llms/oci/test_oci_integration_basic.py -v📝 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.
| uv run pytest tests/llms/oci/test_oci_integration_basic.py -v | |
| uv run pytest lib/crewai/tests/llms/oci/test_oci_integration_basic.py -v |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/crewai/tests/llms/oci/test_oci_integration_basic.py` at line 7, Update
the run instruction that points to tests/llms/oci/test_oci_integration_basic.py
so it uses the correct repository path
(lib/crewai/tests/llms/oci/test_oci_integration_basic.py); change the command
line shown (uv run pytest ...) to reference the full correct path or to run
pytest from repo root (e.g., uv run pytest
lib/crewai/tests/llms/oci/test_oci_integration_basic.py -v) so contributors can
execute the test as written.
|
Hi @greysonlalonde @lorenzejay — gentle nudge from the maintainer team. This PR has been waiting for a fresh review since 2026-03-19. Since the last update:
This is the scoped-down split that @greysonlalonde requested back in #4885. Happy to address any remaining concerns. Is there a way to get this into a review queue? |
|
This PR is stale because it has been open for 45 days with no activity. |
- OCICompletion(BaseLLM): sync call() and async acall() for generic (Meta, Google, OpenAI, xAI) and Cohere model families - Shared OCI auth utilities (utilities/oci.py): API key, security token, instance principal, and resource principal auth - Provider routing in llm.py: oci/ prefix and OCI model-id patterns - oci registered as optional dependency (crewai[oci]) - Configurable timeout via DEFAULT_OCI_TIMEOUT constant - Cohere and generic request/response paths fully separated Tracking issue: crewAIInc#4944 Part 1 of series: crewAIInc#4959 → crewAIInc#4961 → crewAIInc#4962 → crewAIInc#4963 → crewAIInc#4964 → crewAIInc#4966 → crewAIInc#4982
- 15 unit tests (mocked OCI SDK, no credentials needed) - 2 parametrized integration tests across 4 model families: meta.llama-3.3-70b-instruct, cohere.command-r-plus-08-2024, google.gemini-2.5-flash, openai.gpt-5.2-chat-latest - conftest.py with shared fixtures for both test suites
Previously: any `openai.*` model on the GENERIC api_format route was sent `max_completion_tokens` instead of `max_tokens`. That works for the GPT-5 family (which OCI requires it on with HTTP 400 if you send `max_tokens`), but is inconsistent with `_is_openai_gpt5_family()` already used elsewhere in the same method for temperature and stop. Switch the param-name routing to the same predicate so GPT-4o / GPT-4.1 keep the standard `max_tokens` field, while only `openai.gpt-5*` gets `max_completion_tokens`. Also reword the test pair to reflect the two distinct behaviours. Verified live against OCI us-chicago-1 — all 7 model families pass: openai.gpt-5.5 ok (max_completion_tokens) openai.gpt-5 ok (max_completion_tokens) openai.gpt-4o Ok. (max_tokens) openai.gpt-4.1 ok (max_tokens) meta.llama-3.3-70b-instruct ok meta.llama-4-scout-17b-16e-instruct ok cohere.command-latest ok (CohereChatRequest)
Add reasoning_effort: str | None = None as a constructor kwarg. When set, it's passed as `reasoning_effort` on the OCI GenericChatRequest — honoured by GPT-5 family, Gemini 2.5, Grok reasoning variants, and Cohere Command-A-Reasoning; ignored by non-reasoning models. Single biggest cost knob for reasoning-capable models on OCI: setting "LOW" typically cuts reasoning-token spend 5-10×. Other GenericChatRequest fields (verbosity, parallel_tool_calls, logit_bias, n, metadata, etc.) aren't exposed — they either duplicate existing controls or aren't missing primitives.
Coderabbit's pre-merge check flagged 45.10% docstring coverage on this PR; required threshold is 80%. Add concise docstrings for the remaining 14 methods on OCICompletion (init, provider helpers, message helpers, response extractors, call/acall, _chat). Coverage now 100% per ast walk; no behavioural change.
Drop unreachable os.getenv defaults in the live-config fixture and fix the pytest path in the run instructions to include the lib/crewai/ prefix.
|
Rebased onto current main (85c467d) — merge conflicts resolved, PR is mergeable again. Also addressed both CodeRabbit comments: the unreachable Verified live against OCI Generative AI on-demand (us-chicago-1): basic completion passes for all five current model families — |
|
@joaomdmoura @lorenzejay this provider stack is ready for review — rebased onto current main this week, all mergeable, and verified live against OCI Generative AI on-demand (all five current model families, plus the Cohere v2 vision format). Suggested review order (each PR builds on the previous):
Happy to squash the stack into fewer PRs if you'd prefer it that way. |
Summary
OCICompletion) supporting generic (Meta, Google, OpenAI, xAI) and Cohere model familiesutilities/oci.py) for API key, security token, instance principal, and resource principal authcrewai[oci])meta.llama-3.3-70b-instruct,cohere.command-r-plus-08-2024,google.gemini-2.5-flash,openai.gpt-5.2-chat-latest)This is PR 1 of a series — follow-up PRs will add streaming, tool calling, structured output, multimodal, and embeddings support.
Supersedes #4885 (closed per reviewer feedback to split by scope).
Tracking issue: #4944
What's included
utilities/oci.pyget_oci_module()+create_oci_client_kwargs()llms/providers/oci/completion.pyOCICompletion(BaseLLM)— init, message building, basic call/acallllm.pypyproject.tomlocioptional dependencyWhat's NOT included (deferred to follow-up PRs)
iter_stream,astream)response_model)Test plan
meta.llama-3.3-70b-instructcohere.command-r-plus-08-2024google.gemini-2.5-flashopenai.gpt-5.2-chat-latestcall) and async (acall) paths verifiedNote
Medium Risk
Introduces a new native LLM provider and OCI authentication paths; risk is mainly around request/response translation and credential/config handling for a new external SDK.
Overview
Adds native Oracle Cloud Infrastructure (OCI) Generative AI support for basic chat/text completion via a new
OCICompletionprovider, including model-family request shaping (generic vs Cohere) and sync/async call paths with token-usage tracking.Registers
ocias a supported native provider inLLMrouting (prefix handling + model pattern matching) and adds a sharedutilities/oci.pyhelper for lazy SDK import plus multiple OCI auth modes. Includes an optional dependencycrewai[oci]and a new test suite with mocked-SDK unit tests plus opt-in live integration tests.Reviewed by Cursor Bugbot for commit d7e6ffd. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
New Features
Chores
Tests