Skip to content

feat: Add Oracle Cloud Infrastructure (OCI) Generative AI client support - #718

Merged
daniel-cohere merged 9 commits into
cohere-ai:mainfrom
fede-kamel:feat/oci-client
Apr 9, 2026
Merged

feat: Add Oracle Cloud Infrastructure (OCI) Generative AI client support#718
daniel-cohere merged 9 commits into
cohere-ai:mainfrom
fede-kamel:feat/oci-client

Conversation

@fede-kamel

@fede-kamel fede-kamel commented Jan 26, 2026

Copy link
Copy Markdown
Contributor

Overview

I noticed that the Cohere Python SDK has excellent integration with AWS Bedrock through the BedrockClient implementation. I wanted to contribute a similar integration for Oracle Cloud Infrastructure (OCI) Generative AI service to provide our customers with the same seamless experience.

Motivation

Oracle Cloud Infrastructure offers Cohere's models through our Generative AI service, and many of our enterprise customers use both platforms. This integration follows the same architectural pattern as the existing Bedrock client, ensuring consistency and maintainability.

Implementation

This PR adds comprehensive OCI support with:

Features

  • OciClient (V1 API) and OciClientV2 (V2 API) classes
  • Full authentication support:
    • Config file (default ~/.oci/config)
    • Custom profiles
    • Direct credentials
    • Instance principal (for OCI compute instances)
    • Resource principal
  • Complete API coverage:
    • Embed (all models: english-v3.0, light-v3.0, multilingual-v3.0)
    • Chat with streaming support (Command R and Command A models)
    • V2 API support with Command A models (command-a-03-2025)
  • Region-independent: Uses display names instead of region-specific OCIDs
  • Automatic V1/V2 API detection and transformation

Architecture

  • Follows the proven BedrockClient pattern with httpx event hooks
  • Request/response transformation between Cohere and OCI formats
  • Lazy loading of OCI SDK as optional dependency
  • Connection pooling for optimal performance

Testing

  • 14 comprehensive integration tests (100% passing)
  • Tests cover: authentication, embed, chat, chat_stream, error handling
  • Multiple model variants tested

Documentation

  • README section with usage examples
  • All authentication methods documented
  • Installation instructions for optional OCI dependency

Files Changed

  • src/cohere/oci_client.py (910 lines) - Main OCI client implementation
  • src/cohere/manually_maintained/lazy_oci_deps.py (30 lines) - Lazy OCI SDK loading
  • tests/test_oci_client.py (393 lines) - Comprehensive integration tests
  • README.md - OCI usage documentation
  • pyproject.toml - Optional OCI dependency
  • src/cohere/__init__.py - Export OciClient and OciClientV2

Test Results

14 passed, 8 skipped, 0 failed

Skipped tests are for OCI service limitations (base models not callable via on-demand inference).

Breaking Changes

None. This is a purely additive feature.

Checklist

  • Code follows repository style (ruff passing)
  • Tests added and passing
  • Documentation updated
  • No breaking changes

Note

Medium Risk
Adds a large new OCI integration layer that rewrites and signs outbound requests and transforms streaming/non-streaming responses, which could introduce subtle compatibility or parsing bugs despite being additive.

Overview
Adds first-class Oracle Cloud Infrastructure support via new OciClient (v1) and OciClientV2 (v2) that route Cohere embed/chat (+ chat_stream) calls through OCI’s Generative AI inference endpoints using httpx event hooks.

Implements OCI auth and request signing (config-file profiles, direct credentials, instance/resource principals, and session-token refresh), plus bidirectional payload/stream event translation between Cohere and OCI formats (including model-name normalization and v2 content-block lifecycle handling).

Exposes the new clients from cohere.__init__, adds optional oci dependency/extras in pyproject.toml, documents usage in README.md, and introduces a comprehensive tests/test_oci_client.py suite covering auth, transformations, and live integration (gated by env vars).

Reviewed by Cursor Bugbot for commit a06825a. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread pyproject.toml Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
@fede-kamel

fede-kamel commented Jan 26, 2026

Copy link
Copy Markdown
Contributor Author

@walterbm-cohere @daniel-cohere @billytrend-cohere

Hey maintainers,

Friendly bump on this PR - would appreciate your feedback when you have a chance. Happy to address any concerns or make changes as needed.

Thanks.

Comment thread src/cohere/oci_client.py
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py
@fede-kamel

Copy link
Copy Markdown
Contributor Author

Addressed Bugbot feedback:

  1. V2 streaming ends with wrong event (High) - Now emits message-end event before returning on [DONE]

  2. Direct OCI credentials can crash (Medium) - Added validation: when oci_user_id is provided, oci_fingerprint and oci_tenancy_id are now required with a clear error message

Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py
@fede-kamel

Copy link
Copy Markdown
Contributor Author

@sanderland Thanks for the approvals on this PR and the others (#717, #698, #697)! What are the next steps to get these merged?

@fede-kamel

Copy link
Copy Markdown
Contributor Author

@sanderland quick ping on this one since you approved earlier - could you please take a final look when you have a moment? Thanks!

Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py
Comment thread src/cohere/oci_client.py
Comment thread src/cohere/oci_client.py
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
@fede-kamel

Copy link
Copy Markdown
Contributor Author

@billytrend-cohere @walterbm-cohere @daniel-cohere @sanderland

This PR is the canonical Oracle proposal for OCI support in cohere-python, and it now reflects the review feedback that was actionable for the OCI integration scope.

What is in scope on this branch:

  • OciClient and OciClientV2 support for OCI authentication flows
  • embed, chat, and streaming support
  • V2 request/response and streaming handling aligned with the existing SDK surface
  • focused OCI regression coverage and live OCI validation

Current verification on this branch:

  • focused OCI/AWS suite passes locally
  • live OCI validation passes for the runnable cases under the available OCI profiles
  • remaining skips are expected OCI model or region availability gaps, not code failures

Please treat #718 as the official Oracle OCI integration proposal going forward. If there are any remaining blockers to merge, please call them out directly on this PR and I will address them here.

@fede-kamel

Copy link
Copy Markdown
Contributor Author

Final test run — 47/47 passed

All tests passing against the live OCI GenAI inference layer (us-chicago-1):

tests/test_oci_client.py::TestOciClient::test_chat PASSED                [  2%]
tests/test_oci_client.py::TestOciClient::test_chat_stream PASSED         [  4%]
tests/test_oci_client.py::TestOciClient::test_embed PASSED               [  6%]
tests/test_oci_client.py::TestOciClientV2::test_chat_stream_v2 PASSED    [  8%]
tests/test_oci_client.py::TestOciClientV2::test_chat_v2 PASSED           [ 10%]
tests/test_oci_client.py::TestOciClientV2::test_embed_v2 PASSED          [ 12%]
tests/test_oci_client.py::TestOciClientV2::test_embed_with_model_prefix_v2 PASSED [ 14%]
tests/test_oci_client.py::TestOciClientAuthentication::test_config_file_auth PASSED [ 17%]
tests/test_oci_client.py::TestOciClientAuthentication::test_custom_profile_auth PASSED [ 19%]
tests/test_oci_client.py::TestOciClientErrors::test_invalid_model PASSED [ 21%]
tests/test_oci_client.py::TestOciClientErrors::test_missing_compartment_id PASSED [ 23%]
tests/test_oci_client.py::TestOciClientModels::test_command_a_chat PASSED [ 25%]
tests/test_oci_client.py::TestOciClientModels::test_embed_english_v3 PASSED [ 27%]
tests/test_oci_client.py::TestOciClientModels::test_embed_multilingual_v3 PASSED [ 29%]
tests/test_oci_client.py::TestOciClientTransformations (33 unit tests) ALL PASSED [31-100%]

======================= 47 passed in 7.90s ========================

V1 (OciClient) — Command R family, COHERE apiFormat

Test Model Result
test_embed embed-english-v3.0 2x 1024-dim float vectors
test_chat command-r-08-2024 V1 text response
test_chat_stream command-r-08-2024 V1 text-generation stream events

V2 (OciClientV2) — Command A family, COHEREV2 apiFormat

Test Model Result
test_embed_v2 embed-english-v3.0 dict with float_ key
test_chat_v2 command-a-03-2025 V2 message response
test_chat_stream_v2 command-a-03-2025 V2 content-delta SSE events

Validation tests

Test What it proves
test_v2_client_rejects_v1_request OciClientV2 + V1 body → clear ValueError
test_v1_client_rejects_v2_request OciClient + V2 body → clear ValueError

Fern safety

Comment thread src/cohere/aws_client.py
Comment thread src/cohere/manually_maintained/cohere_aws/client.py Outdated
Comment thread src/cohere/manually_maintained/streaming.py
@fede-kamel

Copy link
Copy Markdown
Contributor Author

@mkozakov Quick summary of where everything stands — all work is done and tested on our side.

3 PRs, all ready for review:

  1. cohere-python#718 (this PR) — OCI client with OciClient (V1) + OciClientV2 (V2), 47 tests passing live against OCI GenAI
  2. cohere-python#698 — embed_stream() for memory-efficient embedding, 9 unit tests + 6 e2e validated via OCI
  3. cohere-developer-experience#712 — one-line Fern config change so OciClient/OciClientV2 survive init.py regeneration

All code is Fern-safe — zero auto-generated files modified across any of these PRs. Let me know if anything needs adjustment.

@mkozakov

mkozakov commented Apr 2, 2026

Copy link
Copy Markdown
Collaborator

Hey @fede-kamel finally had a chance to review. In general this looks good, but not sure why this PR touches the AWS client / removes tests?

Comment thread README.md
Comment thread README.md Outdated
Comment thread src/cohere/aws_client.py
Adds OciClient (V1 API) and OciClientV2 (V2 API) for the OCI Generative
AI service, following the BedrockClient pattern with httpx event hooks.

Authentication: config file, custom profiles, session tokens, direct
credentials, instance principal, resource principal.

API coverage: embed (all models), chat with streaming (OciClient for
Command R family, OciClientV2 for Command A). Lazy-loads oci SDK as an
optional dependency; install with `pip install cohere[oci]`.
…profile

- README: remove specific model names from Supported APIs and Model
  Availability sections (per mkozakov review — will go out of date)
- tests: default OCI_PROFILE to DEFAULT instead of API_KEY_AUTH
@fede-kamel

Copy link
Copy Markdown
Contributor Author

Hey @mkozakov — yes, all addressed! Here's the summary:

AWS client / removed tests: Good catch. An earlier iteration of this branch touched the AWS client and removed the AWS unit tests as a side effect. That's all been fully reverted — aws_client.py, cohere_aws/client.py, and test_aws_client_unit.py are back to exactly what's on main. This PR now only touches OCI files.

All 3 inline comments from your review are addressed:

  • Removed specific model names from the Supported OCI APIs list (won't go stale)
  • Removed specific model names from the Model Availability section (same reason)
  • Reverted all AWS client changes (see above)

Branch has been squashed to 2 clean commits:

  1. feat: Add Oracle Cloud Infrastructure (OCI) Generative AI client support
  2. fix: address review feedback — remove stale model names and fix test profile

Tests: 47/47 passing against live OCI GenAI (us-chicago-1).

Comment thread src/cohere/oci_client.py Outdated
The "stream" in endpoint check was dead code — both V1 and V2 SDK always
route through endpoint "chat" (v1/chat and v2/chat paths). Streaming is
reliably signalled via body["stream"], which the SDK always sets.

- Drop "stream" in endpoint guard on is_stream and isStream detection
- Remove "chat_stream" from action_map, transform, and response branches
- Update unit tests to use "chat" endpoint (the only real one)
Comment thread src/cohere/oci_client.py Outdated
_current_content_type now returns None for events with no message content
(e.g. {"finishReason": "COMPLETE"}). The transition branch in
_transform_v2_event is skipped when event_content_type is None, so a
finish-only event after a thinking block no longer opens a spurious empty
text block before emitting content-end.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

There are 3 total unresolved issues (including 1 from previous review).

Fix All in Cursor

Comment thread src/cohere/oci_client.py Outdated
Comment thread src/cohere/oci_client.py Outdated
… token per-request

- transform_request_to_oci now raises ValueError for endpoints other than
  'embed' and 'chat' instead of silently returning the untransformed body
- Session token auth uses a refreshing wrapper that re-reads the token file
  before each signing call, so OCI CLI token refreshes are picked up without
  restarting the client
- Add test_unsupported_endpoint_raises to cover the new explicit error
- Update test_session_auth_prefers_security_token_signer to expect multi-call
  behaviour from the refreshing signer
test_session_token_refreshed_on_subsequent_requests writes a real token file,
makes two requests with the file updated between them, and asserts that the
second signing call uses the new token — verifying the refreshing signer works
end-to-end.
@fede-kamel
fede-kamel requested a review from mkozakov April 4, 2026 17:44
Comment thread src/cohere/oci_client.py
@fede-kamel

fede-kamel commented Apr 9, 2026

Copy link
Copy Markdown
Contributor Author

Is there by chance a response_id you can use? cc: @daniel-cohere

Confirmed from the OCI side — just tested both V1 and V2 responses against the live OCI GenAI inference service:

V2 (Command A, COHEREV2 format): The response includes an id field (e.g. 51122e24-2c71-40e3-bc26-d13db4e89c40), which the code already maps correctly. No response_id or generation_id exists in the schema.

V1 (Command R, COHERE format): The response has no ID fields at all — no id, response_id, generation_id, or request_id. The only ID available is opc-request-id in the HTTP headers, but that's a request-level trace ID (three-part format), not a response/generation identifier.

So the synthetic uuid.uuid4() for V1 is the only option — OCI simply doesn't expose a response-level ID in the V1 chat schema.

@daniel-cohere
daniel-cohere enabled auto-merge (squash) April 9, 2026 16:30
@daniel-cohere
daniel-cohere merged commit 152dbb1 into cohere-ai:main Apr 9, 2026
1 check passed
daniel-cohere pushed a commit to cohere-ai/cohere-developer-experience that referenced this pull request Apr 9, 2026
#712)

Add OCI client exports so they survive Fern regeneration of __init__.py.
Follows the same pattern as BedrockClient/SagemakerClient.

Related: cohere-ai/cohere-python#718
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.

4 participants