Skip to content

Conversation

seridescent
Copy link
Contributor

the fix is super small but the reason is kind of interesting.

IIUC, the intention of #2528 was to allow Azure users to hit a chat completions endpoint
(%baseURL%/deployments/%Model%/chat/completions?api-version=%apiVersion%) instead of a responses endpoint.

i work somewhere that currently only has access to a chat completions endpoint, but when i tried this out, the appropriate configuration still errored. i was connecting to the expected endpoint, but AI SDK was complaining that the prompt was invalid.

turns out, both sdk.completion and sdk.chat ultimately hit a /chat/completions endpoint when called here by opencode. however, i'm pretty sure sdk.completion is supposed to hit /completions instead of /chat/completions; i haven't tracked down why, but that's what happens AFAICT.

anyway, the code paths for a chat language model differ a bit from a completion language model. most notably, a completion language model complains if the prompt has more than one system message while a chat language model does not care.

since opencode may include more than one system message, the completions model would complain.

swapping to a chat language model solves this problem. also, i think it's just more accurate with respect to what functionality is supposed to be exposed.

related: #2528 , #1508 , #3150

the fix is super small but the reason is kind of interesting.

IIUC, the intention of sst#2528 was to allow Azure users to hit a chat
completions endpoint
(`%baseURL%/deployments/%Model%/chat/completions?api-version=%apiVersion%`)
instead of a responses endpoint.

i work somewhere that currently only has access to a chat completions
endpoint, but when i tried this out, the appropriate configuration still
errored. i was connecting to the expected endpoint, but AI SDK was
complaining that the prompt was invalid.

turns out, both `sdk.completion` and `sdk.chat` ultimately hit a
`/chat/completions` endpoint when called here by opencode. however, i'm
pretty sure `sdk.completion` is *supposed to* hit `/completions` instead
of `/chat/completions`; i haven't tracked down why, but that's what
happens AFAICT.

anyway, the code paths for a chat language model differ a bit from a
completion language model. most notably, a completion language model
[complains if the prompt has more than one system
message](https://github.com/vercel/ai/blob/34407b23b8c276359ac8dbeb42cc06f9db301b99/packages/openai/src/completion/convert-to-openai-completion-prompt.ts#L31)
while a chat language model does not care.

since opencode [may include more than one system
message](https://github.com/sst/opencode/blob/1c59530115d05e0f18f381023f639accc851825c/packages/opencode/src/session/prompt.ts#L413),
the completions model would complain.

swapping to a chat language model solves this problem. also, i think
it's just more accurate with respect to what functionality is supposed
to be exposed.
@rekram1-node
Copy link
Collaborator

rekram1-node commented Oct 16, 2025

This is very detailed, and I like it, can you clarify one thing (i haven't looked into the azure provider enough):

What is a little weird to me is all the other people had /chat/completions and the guy that made pr said he had it working?

Any idea why it was working for him but not you? the paths you are using seem the same

@seridescent
Copy link
Contributor Author

honestly i dont know, mostly because i dont know why sdk.completions hit /chat/completions instead of /completions. the bit of ai-sdk code i looked at seemed to handle that case correctly.

given that the error is specifically thrown because of multiple system messages, i would have guessed that they happened to not have multiple system messages in their prompt. OTOH, it looks like resolveSystemPrompt has always returned 2 system messages... ¯\_(ツ)_/¯

@rekram1-node
Copy link
Collaborator

rekram1-node commented Oct 16, 2025

@enlilz can you test this by chance with your setup?

What's weird here is that the vercel ai sdk docs seem to indicate that .completions should work: https://ai-sdk.dev/providers/ai-sdk-providers/azure#chat-models

Oo from vercel ai source code:

  /**
Creates an Azure OpenAI chat model for text generation.
   */
  chat(deploymentId: string): LanguageModelV3;

  /**
Creates an Azure OpenAI responses API model for text generation.
   */
  responses(deploymentId: string): LanguageModelV3;

  /**
Creates an Azure OpenAI completion model for text generation.
   */
  completion(deploymentId: string): LanguageModelV3;

@rekram1-node
Copy link
Collaborator

rekram1-node commented Oct 16, 2025

Ahhh I think it's because of the api version 2025-01-01-preview

@seridescent what happens if you add this to your opencode.json config:

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "azure": {
      "options": {
        "apiVersion": "2025-01-01-preview"
      }
    }
  }
}

^ I think this should make it send that as the apiVersion

@seridescent if you can confirm that doing this^^ works on pushed code, do you think we could adjust the conditional to check the apiVersion?

If it is "2025-01-01-preview" it should use the existing flow, if it is v1 or undefined it should use .chat(...) like your pr did

I think that should work as expected

@seridescent
Copy link
Contributor Author

i have run v0.15.3 both with and without apiVersion set. both don't work.

im also curious, where is this branch to .chat(...) based on apiVersion you're referring to?

@rekram1-node
Copy link
Collaborator

I was looking at this commit: vercel/ai@3771a27

And I was trying to identify any difference between those other peoples setup and your own

@seridescent
Copy link
Contributor Author

seridescent commented Oct 16, 2025

got it. yeah the apparent inconsistency really is bizarre. idt apiVersion is the culprit unfortunately, it looks like it just sets a URL query param and is independent of deployment-based URLs and specific endpoint paths.

also FWIW, the chat models snippet you linked on the vercel ai-sdk docs uses plain azure('deployment-name'), which calls createChatModel and not createCompletionModel. the docs thus make me think that plain/.chat is the "blessed" way to hit that URL in the info box

@rekram1-node
Copy link
Collaborator

rekram1-node commented Oct 16, 2025

apiVersion is the culprit unfortunately, it looks like it just sets a URL query param and is independent of deployment-based URLs and specific endpoint paths.

I saw a comment somewhere about the compatibility the azure api sends data back, so I was wondering if that is what was causing the issue, not necessarily that the logic was handled at the ai sdk level

Hm okay, this makes sense to me, I think we can go ahead and merge and then address any hiccups later

@rekram1-node rekram1-node merged commit 5369345 into sst:dev Oct 16, 2025
3 checks passed
@enlilz
Copy link
Contributor

enlilz commented Oct 16, 2025

@rekram1-node tested it with 0.15.4 (that should include this change) works fine for me, no issues found on a quick test.

i still see some issues with url generation for Azure Ai models, gpt-5-mini breaks all the possible configuration for me (would also not work with the old options before this pr) gpt-5-chat provides a url in azure that can be used by the configuration.

@seridescent what models are you currently using in Azure Ai ? maybe you can also have a look at opencode doc pr and give your input

@rekram1-node
Copy link
Collaborator

thanks!

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.

3 participants