Compare commits

...

6 Commits

Author SHA1 Message Date
localai-org-maint-bot
9ac8bfcdd0 fix(vllm): restore CPU torch build
The CPU requirements were updated to an XPU-only torch wheel, which cannot resolve from the configured CPU index and also breaks vLLM's pinned CPU wheel compatibility. Restore the supported CPU pin; Intel continues to obtain its XPU torch dependency from upstream requirements/xpu.txt.

Assisted-by: Codex:gpt-5
2026-07-30 05:08:01 +00:00
localai-org-maint-bot
bdefd28d84 Merge master into dependabot/pip/backend/python/vllm/torch-2.13.0xpu
Assisted-by: Codex:gpt-5
2026-07-30 05:08:01 +00:00
Tai An
efb43776ba fix(chatterbox): pin cublas12 torch/transformers and setuptools so the backend loads (fixes #11070) (#11074)
fix(chatterbox): pin cublas12 torch/transformers and setuptools so the backend loads

The cuda12-chatterbox gallery backend fails to load on a fresh install
because several deps in requirements-cublas12.txt are unpinned:

- torch/torchaudio: unlike requirements-cublas13.txt and
  requirements-cpu.txt, this file has no --extra-index-url, so pip pulls
  a wheel whose CUDA runtime (cu130) is newer than the host driver
  supports ("NVIDIA driver on your system is too old"). Add the cu124
  index and pin torch/torchaudio 2.6.0+cu124.
- transformers: resolves to 5.x, which dropped LlamaConfig.rope_theta
  that chatterbox-tts 0.3.1's T3 config still reads. Cap to <5.
- setuptools: 81+ dropped pkg_resources, which perth imports under a
  bare try/except and silently sets PerthImplicitWatermarker=None,
  making ChatterboxTTS.__init__ raise 'NoneType' object is not callable.
  Cap to <81 in requirements.txt.

Fixes #11070

Signed-off-by: Tai An <antai12232931@anaiguo.com>
Co-authored-by: Tai An <antai12232931@anaiguo.com>
Co-authored-by: localai-org-maint-bot <bot-opensource@localaisrl.com>
2026-07-30 00:23:45 +02:00
mudler's LocalAI [bot]
d8a1e3c2e4 fix(realtime): echo response.metadata on response.created and response.done (#11198)
response.create accepts a metadata map and ResponseCreateParams has carried
the field all along, but triggerResponse never copied it onto the Response it
emits, so both terminals went out with metadata omitted.

That field is the only thing tying a terminal event back to the
response.create that asked for it. Our own doc comment on ResponseCreateEvent
says so — "the metadata field is a good way to disambiguate multiple
simultaneous Responses" — and it is what makes an out-of-band response
(conversation: "none") usable at all: a client running one alongside the
spoken conversation has no way to tell its own answer from the conversation's,
so it waits for a reply it already received and gave away.

Found from the client side: a headless text turn injected into a live session
was answered correctly in about a second, and the caller still blocked until
its own two-minute timeout because it could not recognise the answer.

Carry the map on liveResponse so all three terminals (in_progress, cancelled,
completed) report it, and leave it omitted when response.create sent none.

Assisted-by: Claude:claude-opus-5 gofmt

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
2026-07-29 23:17:31 +02:00
localai-org-maint-bot
5910d4e0a1 Merge branch 'master' into dependabot/pip/backend/python/vllm/torch-2.13.0xpu 2026-07-29 15:04:51 +02:00
dependabot[bot]
09aab62fdb chore(deps): bump torch in /backend/python/vllm
Bumps torch from 2.9.1+cpu to 2.13.0+xpu.

---
updated-dependencies:
- dependency-name: torch
  dependency-version: 2.13.0+xpu
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-29 09:06:50 +00:00
5 changed files with 114 additions and 17 deletions

View File

@@ -1,6 +1,7 @@
torch
torchaudio
transformers
--extra-index-url https://download.pytorch.org/whl/cu124
torch==2.6.0+cu124
torchaudio==2.6.0+cu124
transformers<5
numpy>=1.24.0,<1.26.0
# chatterbox-tts itself is installed with --no-deps in install.sh.
# These are its real runtime deps, mirroring upstream's pyproject.toml
@@ -15,4 +16,4 @@ conformer
safetensors
spacy-pkuseg
pykakasi==2.3.0
accelerate
accelerate

View File

@@ -2,5 +2,5 @@ grpcio==1.71.0
protobuf
certifi
packaging
setuptools
setuptools<81
poetry

View File

@@ -2163,6 +2163,11 @@ type liveResponse struct {
output []types.MessageItemUnion
usage backend.TokenUsage
outcome responseOutcome
// metadata is echoed back on response.created and response.done. It is the
// only thing tying a terminal event to the response.create that asked for
// it, which is what lets a client run an out-of-band response alongside the
// spoken conversation and still recognise its own answer.
metadata map[string]string
}
func (r *liveResponse) addItem(it types.MessageItemUnion) { r.output = append(r.output, it) }
@@ -2192,12 +2197,16 @@ func triggerResponse(ctx context.Context, session *Session, conv *Conversation,
// terminals the legacy code emitted (one response.done per turn, with empty
// Output/Usage) are gone; tool turns are now internal to this single response.
r := &liveResponse{id: generateUniqueID()}
if overrides != nil {
r.metadata = overrides.Metadata
}
sendEvent(t, types.ResponseCreatedEvent{
ServerEventBase: types.ServerEventBase{},
Response: types.Response{
ID: r.id,
Object: "realtime.response",
Status: types.ResponseStatusInProgress,
ID: r.id,
Object: "realtime.response",
Status: types.ResponseStatusInProgress,
Metadata: r.metadata,
},
})
@@ -2208,10 +2217,11 @@ func triggerResponse(ctx context.Context, session *Session, conv *Conversation,
sendEvent(t, types.ResponseDoneEvent{
ServerEventBase: types.ServerEventBase{},
Response: types.Response{
ID: r.id,
Object: "realtime.response",
Status: types.ResponseStatusCancelled,
Output: r.output,
ID: r.id,
Object: "realtime.response",
Status: types.ResponseStatusCancelled,
Output: r.output,
Metadata: r.metadata,
},
})
case outcomeFailed:
@@ -2221,11 +2231,12 @@ func triggerResponse(ctx context.Context, session *Session, conv *Conversation,
sendEvent(t, types.ResponseDoneEvent{
ServerEventBase: types.ServerEventBase{},
Response: types.Response{
ID: r.id,
Object: "realtime.response",
Status: types.ResponseStatusCompleted,
Output: r.output,
Usage: responseUsage(r.usage),
ID: r.id,
Object: "realtime.response",
Status: types.ResponseStatusCompleted,
Output: r.output,
Usage: responseUsage(r.usage),
Metadata: r.metadata,
},
})
}

View File

@@ -263,4 +263,64 @@ var _ = Describe("triggerResponse", func() {
Expect(done.Response.Usage.OutputTokens).To(Equal(3))
Expect(done.Response.Usage.TotalTokens).To(Equal(8))
})
// response.metadata is the only thing tying a terminal event back to the
// response.create that asked for it. Without the echo, a client running an
// out-of-band response alongside the spoken conversation cannot tell its own
// answer from the conversation's, and blocks until it times out.
It("echoes response.create metadata back on response.created and response.done", func() {
m := &fakeModel{
cfg: &config.ModelConfig{},
predictResp: backend.LLMResponse{Response: "Hi there."},
}
session := &Session{
OutputSampleRate: 24000,
ModelInterface: m,
ModelConfig: &config.ModelConfig{},
OutputModalities: []types.Modality{types.ModalityText},
}
t := &fakeTransport{}
triggerResponse(context.Background(), session, &Conversation{}, t, &types.ResponseCreateParams{
Metadata: map[string]string{"client_run": "abc123"},
})
var created *types.ResponseCreatedEvent
var done *types.ResponseDoneEvent
for i := range t.events {
switch e := t.events[i].(type) {
case types.ResponseCreatedEvent:
created = &e
case types.ResponseDoneEvent:
done = &e
}
}
Expect(created).NotTo(BeNil())
Expect(created.Response.Metadata).To(HaveKeyWithValue("client_run", "abc123"))
Expect(done).NotTo(BeNil())
Expect(done.Response.Metadata).To(HaveKeyWithValue("client_run", "abc123"))
})
// Omitted rather than sent as an empty object, matching the omitempty tag.
It("sends no metadata when response.create carried none", func() {
m := &fakeModel{
cfg: &config.ModelConfig{},
predictResp: backend.LLMResponse{Response: "Hi there."},
}
session := &Session{
OutputSampleRate: 24000,
ModelInterface: m,
ModelConfig: &config.ModelConfig{},
OutputModalities: []types.Modality{types.ModalityText},
}
t := &fakeTransport{}
triggerResponse(context.Background(), session, &Conversation{}, t, nil)
for i := range t.events {
if d, ok := t.events[i].(types.ResponseDoneEvent); ok {
Expect(d.Response.Metadata).To(BeEmpty())
}
}
})
})

View File

@@ -347,6 +347,31 @@ By default a realtime session responds with audio plus a transcript. To make the
The GA `output_modalities` wins when both are present. A response-level value overrides the session-level one, and when neither is set the session falls back to `["audio"]`.
### Out-of-band responses and `metadata`
A response can be created outside the default conversation by setting `conversation` to `none`. The reply is not added to the conversation history, which is what makes it usable for a side channel — answering a chat message or a webhook while a spoken conversation is in progress.
Because such a response arrives on the same socket as everything else, attach `metadata` to correlate it. LocalAI echoes the map back verbatim on both `response.created` and `response.done`:
```json
{"type": "response.create", "response": {
"conversation": "none",
"output_modalities": ["text"],
"metadata": {"client_run": "abc123"},
"input": [{"type": "message", "role": "user",
"content": [{"type": "input_text", "text": "Is the oven still on?"}]}]
}}
```
```json
{"type": "response.done", "response": {
"id": "resp_...", "status": "completed",
"metadata": {"client_run": "abc123"}
}}
```
Keys are strings up to 64 characters, values up to 512. A response created without `metadata` omits the field rather than sending an empty object.
## Gating a realtime pipeline with voice recognition
A pipeline realtime model can require speaker verification before it responds. Add a `voice_recognition` block under `pipeline`. When present, each committed utterance is verified against authorized speakers; unauthorized utterances are dropped before the LLM runs (no LLM call, no tool execution, no TTS). The session stays open.