|  | 
| 5 | 5 | # the root directory of this source tree. | 
| 6 | 6 | import asyncio | 
| 7 | 7 | from typing import Any | 
|  | 8 | +from sqlalchemy.exc import IntegrityError | 
| 8 | 9 | 
 | 
| 9 | 10 | from llama_stack.apis.inference import ( | 
| 10 | 11 |     ListOpenAIChatCompletionResponse, | 
| @@ -129,16 +130,44 @@ async def _write_chat_completion( | 
| 129 | 130 |             raise ValueError("Inference store is not initialized") | 
| 130 | 131 | 
 | 
| 131 | 132 |         data = chat_completion.model_dump() | 
| 132 |  | - | 
| 133 |  | -        await self.sql_store.insert( | 
| 134 |  | -            table="chat_completions", | 
| 135 |  | -            data={ | 
| 136 |  | -                "id": data["id"], | 
| 137 |  | -                "created": data["created"], | 
| 138 |  | -                "model": data["model"], | 
| 139 |  | -                "choices": data["choices"], | 
| 140 |  | -                "input_messages": [message.model_dump() for message in input_messages], | 
| 141 |  | -            }, | 
|  | 133 | +        record_data = { | 
|  | 134 | +            "id": data["id"], | 
|  | 135 | +            "created": data["created"], | 
|  | 136 | +            "model": data["model"], | 
|  | 137 | +            "choices": data["choices"], | 
|  | 138 | +            "input_messages": [message.model_dump() for message in input_messages], | 
|  | 139 | +        } | 
|  | 140 | + | 
|  | 141 | +        try: | 
|  | 142 | +            await self.sql_store.insert( | 
|  | 143 | +                table="chat_completions", | 
|  | 144 | +                data=record_data, | 
|  | 145 | +            ) | 
|  | 146 | +        except IntegrityError as e: | 
|  | 147 | +            # Check if it's a unique constraint violation | 
|  | 148 | +            error_message = str(e.orig) if e.orig else str(e) | 
|  | 149 | +            if self._is_unique_constraint_error(error_message): | 
|  | 150 | +                # Update the existing record instead | 
|  | 151 | +                await self.sql_store.update( | 
|  | 152 | +                    table="chat_completions", | 
|  | 153 | +                    data=record_data, | 
|  | 154 | +                    where={"id": data["id"]} | 
|  | 155 | +                ) | 
|  | 156 | +            else: | 
|  | 157 | +                # Re-raise if it's not a unique constraint error | 
|  | 158 | +                raise | 
|  | 159 | + | 
|  | 160 | +    def _is_unique_constraint_error(self, error_message: str) -> bool: | 
|  | 161 | +        """Check if the error is specifically a unique constraint violation.""" | 
|  | 162 | +        error_lower = error_message.lower() | 
|  | 163 | +        return any( | 
|  | 164 | +            indicator in error_lower | 
|  | 165 | +            for indicator in [ | 
|  | 166 | +                "unique constraint failed",  # SQLite | 
|  | 167 | +                "duplicate key",  # PostgreSQL | 
|  | 168 | +                "unique violation",  # PostgreSQL alternative | 
|  | 169 | +                "duplicate entry",  # MySQL | 
|  | 170 | +            ] | 
| 142 | 171 |         ) | 
| 143 | 172 | 
 | 
| 144 | 173 |     async def list_chat_completions( | 
|  | 
0 commit comments