@@ -292,6 +292,10 @@ func (c *AIController) createOpenAIClient() *openai.Client {
292292
293293 aiProvider := aiConfig .GetProvider ()
294294
295+ if aiProvider .Provider == "azure_ai" {
296+ return c .createAzureAIClient (aiProvider )
297+ }
298+
295299 config = openai .DefaultConfig (aiProvider .APIKey )
296300 config .BaseURL = aiProvider .APIHost
297301 if ! strings .HasSuffix (config .BaseURL , "/v1" ) {
@@ -300,6 +304,36 @@ func (c *AIController) createOpenAIClient() *openai.Client {
300304 return openai .NewClientWithConfig (config )
301305}
302306
307+ // createAzureAIClient creates an OpenAI client configured for Azure AI.
308+ // Uses the Azure OpenAI compatibility endpoint: https://{resource}.openai.azure.com/openai/v1
309+ func (c * AIController ) createAzureAIClient (aiProvider * schema.SiteAIProvider ) * openai.Client {
310+ azureBaseURL := strings .TrimRight (aiProvider .APIHost , "/" ) + "/openai/v1"
311+
312+ config := openai .DefaultConfig (aiProvider .APIKey )
313+ config .BaseURL = azureBaseURL
314+ config .HTTPClient = & http.Client {
315+ Transport : & azureAPIKeyTransport {
316+ apiKey : aiProvider .APIKey ,
317+ transport : http .DefaultTransport ,
318+ },
319+ }
320+ return openai .NewClientWithConfig (config )
321+ }
322+
323+ // azureAPIKeyTransport is an http.RoundTripper that replaces the Authorization
324+ // header with the Azure-style api-key header for Azure OpenAI requests.
325+ type azureAPIKeyTransport struct {
326+ apiKey string
327+ transport http.RoundTripper
328+ }
329+
330+ func (t * azureAPIKeyTransport ) RoundTrip (req * http.Request ) (* http.Response , error ) {
331+ req = req .Clone (req .Context ())
332+ req .Header .Del ("Authorization" )
333+ req .Header .Set ("api-key" , t .apiKey )
334+ return t .transport .RoundTrip (req )
335+ }
336+
303337// getPromptByLanguage
304338func (c * AIController ) getPromptByLanguage (language i18n.Language , question string ) string {
305339 aiConfig , err := c .siteInfoService .GetSiteAI (context .Background ())
@@ -497,6 +531,10 @@ func (c *AIController) processAIStream(
497531 break
498532 }
499533
534+ if len (response .Choices ) == 0 {
535+ continue
536+ }
537+
500538 choice := response .Choices [0 ]
501539
502540 if len (choice .Delta .ToolCalls ) > 0 {
0 commit comments