Skip to content

/v1/completions fails on QAIRT models because the qairt plugin rejects stop sequences #1341

Description

Description

FIM autocompletion over the raw /v1/completions endpoint (added in #1317) fails on every QAIRT model. Editor autocomplete clients always send a stop list with the FIM sentinel strings, the handler forwards that list to the plugin unchanged, and the qairt plugin rejects any generate call that carries stop sequences. The result is ErrorCode[-100016] and an empty completion, so /v1/completions is currently unusable with QAIRT models even though the same request works on llama_cpp GGUF models.

This was reported by a user testing FIM autocompletion from a VS Code extension against qualcomm/Qwen3-1.7B:W4A16.

Steps to reproduce

  1. geniex serve
  2. Send a completion request for a QAIRT model with a stop array, the way FIM clients do:
curl http://127.0.0.1:8080/v1/completions -H "Content-Type: application/json" -d "{\"model\":\"qualcomm/Qwen3-1.7B:W4A16\",\"prompt\":\"<fim_prefix>def main():\\n    print(<fim_suffix>)\\n<fim_middle>\",\"stop\":[\"<fim_prefix>\",\"<fim_suffix>\",\"<fim_middle>\",\"<|endoftext|>\"],\"max_tokens\":256,\"stream\":true}"
  1. The completion comes back empty and the server log shows the plugin rejection.

Observed behavior

Aug 13 16:42:19.331 INF handler\completion.go:111 Completions param="{CompletionNewParams:{Prompt:{OfString:<fim_prefix>\n# part2_agents/testcomplete.py\nimport requests\n\n\ndef main():\n    print(\"hello World<fim_suffix>\")\n\n\nif __name__ == \"__main__\":\n    main()\n<fim_middle> ...} Model:qualcomm/Qwen3-1.7B:W4A16 ... MaxTokens:4096 ... Stop:{OfStringArray:[<fim_prefix> <fim_suffix> <fim_middle> <file_sep> <|endoftext|> </fim_middle> </code> /src/ #- coding: utf-8 ```]} ...} Stream:true NCtx:4096 Ngl:-1 Compute:npu ...}"
Aug 13 16:42:19.395 DBG go\llm.go:422 Generate called promptLen=163 inputIDsLen=0
Aug 13 16:42:19.395 ERR go\ml.go:212 [ML] [plugins/qairt/src/llm.cpp:220:generate] --stop / --stop-file (stop sequences) is not supported by the qairt plugin
Aug 13 16:42:19.395 DBG go\ml.go:214 [ML] [src/llm.cpp:143:geniex_llm_generate] ErrorCode[-100016](Parameter not supported by this plugin): LlmGenerateOutput(full_text: nullptr, profile_data: ProfileData(ttft: 0 us, prompt_time: 0 us, decode_time: 0 us, prompt_tokens: 0, generated_tokens: 0, prefill_speed: 0 tokens/s, decoding_speed: 0 tokens/s, stop_reason: nullptr))
[GIN] 2026/08/13 - 16:42:19 | 200 |     65.1308ms |       127.0.0.1 | POST     "/v1/completions"

Where it happens:

  • cli/server/handler/completion.go builds GenerationConfig with Stop: completionStop(req.Stop) and passes it to the plugin for every runtime.
  • sdk/plugins/qairt/src/llm.cpp:219 rejects any generate input with stop_count > 0 and returns GENIEX_ERROR_COMMON_PARAM_NOT_SUPPORTED.

Two side effects worth noting:

  • The HTTP response is 200 even though generation failed, so editor clients silently show nothing instead of surfacing an error.
  • The failure is request-shaped, not model-shaped: the same model works if the client omits stop, but real FIM clients never omit it.

Expected behavior

Stop sequences on /v1/completions should work regardless of which plugin serves the model. For plugins that do not implement stop sequences natively, the server can enforce them host side:

  1. Do not forward Stop to a plugin that rejects it.
  2. Match the stop strings against the streamed text inside the OnToken callback.
  3. Cancel generation when a stop string matches (the qairt pipeline already supports cancellation through the callback return value, reported as stop_reason: "user").
  4. Truncate the returned text at the match so the client receives the completion up to, but not including, the stop sequence.

With that in place the request above returns the FIM completion on QAIRT models exactly as it does on llama_cpp models today, and no plugin changes are required.

Additional context

With GGUF models the same setup works, which confirms the failure is specific to the qairt plugin parameter rejection. I am happy to submit a PR implementing the host side stop handling.

Environment

  • GenieX: current main build
  • Model: qualcomm/Qwen3-1.7B:W4A16 (qairt runtime, NPU)
  • Client: VS Code FIM autocomplete extension via /v1/completions, stream: true
  • OS: Windows 11

Metadata

Metadata

Assignees

No one assigned

    Labels

    🐞 bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions