Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

koxudaxi
Copy link
Collaborator

@koxudaxi koxudaxi commented Sep 22, 2025

TL;DR

Added support for Mistral AI in the Python SDK's telemetry and tracing system.

What changed?

  • Added Mistral AI as a new provider in the Python SDK's OpenTelemetry instrumentation
  • Implemented a _MistralInstrumentor class to handle Mistral client instrumentation
  • Created the instrument_mistral() function to instrument Mistral clients
  • Added necessary dependencies in pyproject.toml for the new Mistral integration
  • Added comprehensive test coverage for both sync and async Mistral client operations
  • Updated the OpenTelemetry initialization to include Mistral instrumentation

How to test?

  1. Install the Mistral dependency:

    pip install lilypad[mistral]
    
  2. Use the instrumentation in your code:

    from mistralai import Mistral
    from lilypad._internal.otel import instrument_mistral
    
    client = Mistral(api_key="your-api-key")
    instrument_mistral(client)
    
    # Now use the client as normal, with telemetry enabled
    response = client.chat.complete(
        model="mistral-small-latest",
        messages=[{"role": "user", "content": "Hello world"}]
    )
  3. Run the tests:

    cd sdks/python
    pytest tests/lilypad/_internal/otel/test_mistral.py
    

Why make this change?

This change extends the SDK's telemetry capabilities to include Mistral AI, allowing users to collect standardized telemetry data when using Mistral models. This is part of the ongoing effort to provide comprehensive observability across all supported LLM providers, making it easier for users to monitor, debug, and analyze their AI applications regardless of which provider they're using.

Copy link

gitguardian bot commented Sep 22, 2025

️✅ There are no secrets present in this pull request anymore.

If these secrets were true positive and are still valid, we highly recommend you to revoke them.
While these secrets were previously flagged, we no longer have a reference to the
specific commits where they were detected. Once a secret has been leaked into a git
repository, you should consider it compromised, even if it was deleted immediately.
Find here more information about risks.


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Copy link
Collaborator Author

koxudaxi commented Sep 22, 2025

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@koxudaxi koxudaxi marked this pull request as ready for review September 22, 2025 08:47
Copy link

github-actions bot commented Sep 22, 2025

🚀 Preview Deployment

Your changes have been deployed to a preview environment:

Preview URL: https://lilypad-pr-703.mirascope.workers.dev

Database Branch: preview/pr-703


Last updated: 2025-10-03T04:12:42Z (Commit: 6da8958)

@koxudaxi koxudaxi force-pushed the LILYPAD-224 branch 6 times, most recently from 98cefac to da91e24 Compare September 22, 2025 11:35
@koxudaxi koxudaxi requested a review from willbakst September 22, 2025 11:36
@willbakst willbakst force-pushed the LILYPAD-223 branch 2 times, most recently from a5a8b79 to e919212 Compare September 23, 2025 18:04
@willbakst willbakst force-pushed the LILYPAD-224 branch 2 times, most recently from 385a27c to c90f218 Compare September 23, 2025 21:30

_MISTRAL_SYSTEM = gen_ai_attributes.GenAiSystemValues.MISTRAL_AI.value

MistralMessage: TypeAlias = (
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: i think these type aliases might make things more confusing

class _MistralKwargs(BaseKwargs, total=False):
"""TypedDict for Mistral chat completion parameters."""

model: Required[str]
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: should have same required vs. not required comments as other providers

server_url: str | None


def _coerce_optional(value: T | None) -> T | None:
Copy link
Contributor

Choose a reason for hiding this comment

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

the type hint on this function doesn't match it's description since it doesn't include UNSET or UNSET_SENTINEL


def _normalize_stop_sequences(stop: Stop | None) -> list[str] | None:
"""Returns normalized stop sequences from Mistral parameters."""
normalized = _coerce_optional(stop)
Copy link
Contributor

Choose a reason for hiding this comment

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

same here, if the type is Stop | None why do we need to coerce?

kwargs.get("server_url") or client.sdk_configuration.get_server_details()[0]
)
parsed = urlparse(server_url or "")
request_attributes = GenAIRequestAttributes(
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: just return this directly

message: Message = {"role": "assistant"}
tool_calls = None
if choice.message:
message_dict = _to_dict(choice.message)
Copy link
Contributor

Choose a reason for hiding this comment

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

note that this is an example proving my earlier comment that _to_dict removes the value of type hints in the following code

if content:
message["content"] = content
tool_calls_value = message_dict.get("tool_calls")
tool_calls_payload = (
Copy link
Contributor

Choose a reason for hiding this comment

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

another reason to push this inside of _convert_tool_calls

return response_attributes, choice_deltas


def instrument_mistral(client: Mistral) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: the formatting on this function doesn't match other providers

_utils.mark_client_as_instrumented(client)


if not hasattr(EventStreamAsync, "close"):
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd like to sync on why we need this

Copy link
Contributor

Choose a reason for hiding this comment

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

no tests for tools reinsertion?

@koxudaxi koxudaxi marked this pull request as draft September 24, 2025 08:40
@koxudaxi koxudaxi force-pushed the LILYPAD-223 branch 2 times, most recently from 04a34fc to b9c8a35 Compare September 30, 2025 01:59
@koxudaxi koxudaxi force-pushed the LILYPAD-223 branch 2 times, most recently from 1f8cbab to bdd704e Compare October 2, 2025 04:00
@koxudaxi koxudaxi force-pushed the LILYPAD-224 branch 2 times, most recently from 479e664 to 436b11a Compare October 2, 2025 04:16
@koxudaxi koxudaxi force-pushed the LILYPAD-223 branch 2 times, most recently from cac29d2 to 3c5de5f Compare October 2, 2025 08:36
@koxudaxi koxudaxi force-pushed the LILYPAD-224 branch 2 times, most recently from 618e158 to 7d0b215 Compare October 3, 2025 03:36
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.

2 participants