Mistral imposes three conversation-history quirks on top of the OpenAI-compatible wire format: tool messages must be followed by an assistant message; non-initial system messages are rejected; trailing assistant messages require `prefix=True`. These rules were applied inline in `MistralLLMService.build_chat_completion_params`, which is the wrong layer — every other provider with OpenAI-compatible-but-quirky shape (Perplexity, etc.) owns its transformations in a `BaseLLMAdapter` subclass that runs during `get_llm_invocation_params`. Create `MistralLLMAdapter(OpenAILLMAdapter)` on the Perplexity template and wire it in via the existing `adapter_class` dispatch. The service now only handles Mistral-specific request-level mapping (`random_seed` in place of `seed`), and the message shape concerns live with other provider format logic. No behavior change. The transform function casts to `list[dict[str, Any]]` internally because mutating `role` and attaching Mistral's non-standard `prefix` field both step outside OpenAI's TypedDict contract; the cast at the return boundary encodes that we're emitting Mistral's extended schema, not OpenAI's.
5.7 KiB
5.7 KiB