Repository navigation
Conversation
… suffix) for editor autocomplete Editor plugins such as Continue send tab autocomplete to OpenAI's legacy /v1/completions; Maya answered 404. The prompt goes to the engine as it is (no chat template, thinking off, no tools), through the same queue, stop strings and timings as a chat answer, and comes back as text_completion (or its SSE chunks). A special token's text in the prompt is that token, so a client that renders its own FIM prompt works; with `suffix`, the server renders it with the model's own markers (DeepSeek's begin/hole/end, Qwen's prefix/suffix/middle), or answers 400 when the vocabulary has none. DeepSeek's BOS goes first unless the prompt has it or add_special is false. Default max_tokens 16 (OpenAI's). MAYA_COMPLETIONS=0 turns the route off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E3U3Q9QVVJFxinHHkEaRu6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Editor plugins such as Continue send tab autocomplete to OpenAI's legacy
/v1/completions, and Maya answered 404. This PR adds that endpoint. The prompt goes to the engine as it is: no chat template, thinking off, no tools. It runs through the same queue, stop strings and timings as a chat answer, and comes back as atext_completion, or its SSE chunks. With asuffix, the server renders the model's own fill-in-the-middle markers (DeepSeek's and Qwen's). A client that renders them itself, as Continue does for an OpenAI-compatible server, works too. Nothing else changes, andMAYA_COMPLETIONS=0turns the route off.On DeepSeek-V4.1-Flash-1017 (UD-Q8_K_XL, one L40S), fill-in-the-middle works. We removed one line from the middle of 127 HumanEval+ solutions. With the code after the gap, the model wrote a line that passes the problem's tests in 94 of 127. With only the code before the gap, it got 30. PHP fills were right too, for example
$dados = json_decode($json, true);.Speed is the limit on this box, and to be honest about it: for keystroke autocomplete our team now uses a small local model. When the prompt is the same as the last one, the answer comes in about 0.3 s. When the user typed something in the middle, the whole prompt is read again: about 7 s for 600 tokens and 10 s for 1,800, because short prompts read at about 90 tok/s here. With a real Continue setup, most suggestions arrived after the user had moved on. On a 16 GB GPU, the size our developers have, Qwen2.5-Coder 7B Base answered in under 0.6 s (p95). We still think the endpoint belongs in Maya: it lets one server do both on faster hardware, and it gives the speed-ups below something to aim at.
🤖 Humans can stop reading here. Machines, carry on.
The rest is data and method, so an agent or LLM can reproduce our numbers. It is not a prompt to paste.
What the PR changes (server only, no engine change):
serve/server.py:Service.completion_idsandService.fim_markers;completion_chunks/completion_collect, which reuseopenai_chunkswith thinking off and no tools and reshape its chunks;_completions, and the route indo_POST, including the busy 503 check.serve/test_completions.py: 13 tests against the mock engine:max_tokens16;echo,n,logprobs, empty prompt, andsuffixon a vocabulary without FIM tokens;suffixrendering;add_special: false;/v1/chat/completionsunchanged;docs/SETTINGS.md: a section and theMAYA_COMPLETIONSrow.Request handling:
promptmay be a string, a one-element list, or a list of token ids. Several prompts at once get a 400./tokenizedoes.suffixis rendered with the first marker set the vocabulary has as single tokens (the same single-token teststop_idsuses):<|fim▁begin|>{prompt}<|fim▁hole|>{suffix}<|fim▁end|>;<|fim_prefix|>{prompt}<|fim_suffix|>{suffix}<|fim_middle|>.<|begin▁of▁sentence|>is prepended unless present oradd_special: false.logprobs,echo,n/best_ofabove 1 get a 400.Tests run:
python -m unittest discover -s serve -p "test_*.py" -t .with this change on main (v1.1.58): 949 tests, all pass except 17 failures and 1 error. It was run on v1.1.57 too, with the same result.test_dashboard,test_glm_dsa_modelsPageJs,test_glm_dsa_serveWebAppHistory,test_glm_dsa_think_budget,test_turbo), and our box's Node.js is v12.Real model run (v1.1.57 engine, this branch's server, one L40S-48Q, 32 vCPU, Linux; production config,
--parallel 2, DSpark on):suffix, rendered by the serverstop: ["\n"],max_tokens64. The rebuilt function ran the problem's base tests. With the original line, all 127 pass.N-1 reused + 1 read).Latency, server-rendered FIM, a prefix from this repository's code,
max_tokens32:prompt 426 tokens = 0 reused + 426 read in 4745 ms). The same prompt again is425 reused + 1 read in 46 ms.With Continue on a real project (one developer, PHP, about 25 minutes with the route on): 58 autocomplete requests.
max_tokens4096,temperature0.01, about 650 prompt tokens, stop list with//and<|end▁of▁sentence|>.done: 0 tokens in 11 s (cancel).What we use for keystroke autocomplete meanwhile (our lab's other run, a different harness, so not comparable with the HumanEval numbers above):
Not in this PR, ideas for after it:
deepseek_restore_pointsonly marks turn openers and drops points underRESTORE_LEAST(1024). For a FIM prompt, a mark shortly before<|fim▁hole|>would let the next keystroke re-read only the end of the prefix and the suffix. With short prompts reading at ~90 tok/s here, the 1024 floor is too high for this case.Checked:
max_tokens) and r717 (content parts) passed, with 0 engine errors.Related:
DS4_FLOW_COPY_DMAalso where the RAM copies are split across CPU sockets - short prompts 11-16% faster on two sockets, the same bits #958 and DeepSeek: a short prompt's least-picked RAM experts on the CPU lane while the GPU streams the rest (MAYA_DS4_PREFILL_CPU, opt-in) - an agent's turn ~40% faster on PCIe 3.0 #959 (DMA and CPU work for short prompt reads): they target the ~90 tok/s short-prompt reads above. Their author measured 500-700-token agent turns going from 8.9-9.7 s to 4.1-4.9 s. We have not run them here yet.--parallel N: one waiting request cuts all N running answers, not one #882 and DeepSeek: a long prompt freezes the running answers for its whole read (4.3 s at 4K) - a pause between layers takes it to 0.4 s, the same bits #930: short requests waiting behind long ones under--parallel; autocomplete requests are short and frequent./v1/completionsor FIM in this repository, Strata, Colibri, Avalon, Basalt or Xolotl.🤖 Generated with Claude Code
https://claude.ai/code/session_01E3U3Q9QVVJFxinHHkEaRu6