Codec for OpenAI Chat Completions API payloads. Decodes flat dict payloads (messages, model, temperature, etc.) into AnnotatedLLMRequest. Unrecognized keys go to extra for lossless round-trip.
| 24 | |
| 25 | |
| 26 | class OpenAICodec(LlmCodec): |
| 27 | """Codec for OpenAI Chat Completions API payloads. |
| 28 | |
| 29 | Decodes flat dict payloads (messages, model, temperature, etc.) into |
| 30 | AnnotatedLLMRequest. Unrecognized keys go to extra for lossless |
| 31 | round-trip. |
| 32 | """ |
| 33 | |
| 34 | _PARAM_KEYS = {"temperature", "max_tokens", "max_completion_tokens", "top_p", "stop"} |
| 35 | _MODELED_KEYS = {"messages", "model", "tools", "tool_choice"} | _PARAM_KEYS |
| 36 | |
| 37 | def decode(self, request): |
| 38 | c = request.content |
| 39 | messages = c.get("messages", []) |
| 40 | model = c.get("model") |
| 41 | params = {} |
| 42 | for k in self._PARAM_KEYS: |
| 43 | if k in c and c[k] is not None: |
| 44 | # Normalize max_completion_tokens -> max_tokens |
| 45 | key = "max_tokens" if k == "max_completion_tokens" else k |
| 46 | params[key] = c[k] |
| 47 | extra = {k: v for k, v in c.items() if k not in self._MODELED_KEYS} |
| 48 | return AnnotatedLLMRequest( |
| 49 | messages, |
| 50 | model=model, |
| 51 | params=params or None, |
| 52 | tools=c.get("tools"), |
| 53 | tool_choice=c.get("tool_choice"), |
| 54 | extra=extra or None, |
| 55 | ) |
| 56 | |
| 57 | def encode(self, annotated, original): |
| 58 | content = dict(original.content) |
| 59 | content["messages"] = annotated.messages |
| 60 | if annotated.model is not None: |
| 61 | content["model"] = annotated.model |
| 62 | if annotated.params: |
| 63 | for k, v in annotated.params.items(): |
| 64 | # Write back to max_completion_tokens when original used that key |
| 65 | if k == "max_tokens" and "max_completion_tokens" in original.content: |
| 66 | content["max_completion_tokens"] = v |
| 67 | else: |
| 68 | content[k] = v |
| 69 | if annotated.tools is not None: |
| 70 | content["tools"] = annotated.tools |
| 71 | if annotated.tool_choice is not None: |
| 72 | content["tool_choice"] = annotated.tool_choice |
| 73 | if annotated.extra: |
| 74 | for k, v in annotated.extra.items(): |
| 75 | content[k] = v |
| 76 | return LLMRequest(original.headers, content) |
| 77 | |
| 78 | |
| 79 | class NIMCodec(OpenAICodec): |
no outgoing calls