Files
ollama/model/renderers/speech.go
Daniel HiltgenandGitHub 3fbc609be4 llm: LFM3 GGUF fixes and llama-server speech (#19344)
Fixes for running LFM3 GGUFs on the llama-server runner, plus GGUF
text-to-speech that turns on once llama.cpp is bumped past b11901.

- BOS: honor an explicit tokenizer.ggml.add_bos_token. LFM3 GGUFs (and
  lfm2:24b) set it to false and expect the template's BOS, which the
  lfm2 default was stripping. The lfm2 default still applies when the
  key is absent. On lfm2:24b, WikiText PPL goes from 81.3 to 72.0.
- repeat_last_n -1 now maps to the context size; llama-server rejects
  negative values.
- Audio-only projectors (LFM3-Audio) no longer advertise vision, so
  clients don't send images the model can't take.
- /v1/audio/speech on GGUF models calls llama-server /tts chunk by
  chunk. Renderers opt in through a new SpeechPrompter (voices,
  voice parsing, chunking), so other speech models can add their own.
  The LFM3 voice and chunking helpers move from the MLX runner into
  model/renderers and are shared by both runners.
2026-10-27 18:56:22 -07:00

36 lines
1.3 KiB
Go

package renderers
// SpeechVoice is the voice and language a llama-server /tts request asks for.
type SpeechVoice struct{ Voice, Language string }
// SpeechChunk is one /tts generation of a speech request.
type SpeechChunk struct {
// Text is read aloud, escaped for the model's tts template.
Text string
// MaxFrames caps the codec frames the generation may produce.
MaxFrames int
}
// SpeechPrompter maps speech requests onto llama-server's /tts for the models
// a renderer serves; llama-server renders the model's own TTS template.
type SpeechPrompter interface {
// SpeechVoices lists the voice names to advertise; renderers whose models
// do not speak return none.
SpeechVoices() []string
// SpeechVoice resolves a voice name; the client gets a 400 on error.
SpeechVoice(name string) (SpeechVoice, error)
// SpeechChunks splits input into generations, or returns nil when there is
// no text to speak; count returns the token count of a piece of text.
SpeechChunks(input string, count func(string) int) []SpeechChunk
}
// SpeechPrompterForRenderer returns the named renderer's SpeechPrompter if
// its models read text aloud through llama-server.
func SpeechPrompterForRenderer(name string) (SpeechPrompter, bool) {
p, ok := rendererForName(name).(SpeechPrompter)
if !ok || len(p.SpeechVoices()) == 0 {
return nil, false
}
return p, true
}