feat(uploads): choose the language of a recording; Swedish default, Other = auto (#61 interim) #62
@@ -71,9 +71,20 @@ func (g *Gateway) Transcribe(ctx context.Context, path string) (domain.Transcrip
|
||||
return domain.Transcription{}, fmt.Errorf("transcribe: stat audio: %w", err)
|
||||
}
|
||||
|
||||
// The language is one request field and a closed set: sv is sent, auto sends nothing so
|
||||
// the engine detects it, and anything else never leaves this process (tapir#61).
|
||||
fields := [][2]string{{"model", g.model}, {"response_format", "verbose_json"}}
|
||||
switch lang := domain.LanguageFrom(ctx); lang {
|
||||
case domain.LangSwedish:
|
||||
fields = append(fields, [2]string{"language", string(lang)})
|
||||
case domain.LangAuto:
|
||||
default:
|
||||
return domain.Transcription{}, fmt.Errorf("transcribe: language %q is not one tapir sends", lang)
|
||||
}
|
||||
|
||||
var prefix bytes.Buffer
|
||||
mw := multipart.NewWriter(&prefix)
|
||||
for _, kv := range [][2]string{{"model", g.model}, {"response_format", "verbose_json"}, {"language", "sv"}} {
|
||||
for _, kv := range fields {
|
||||
if err := mw.WriteField(kv[0], kv[1]); err != nil {
|
||||
return domain.Transcription{}, fmt.Errorf("transcribe: build request: %w", err)
|
||||
}
|
||||
|
||||
@@ -255,3 +255,48 @@ func TestGateway_AnErrorBodyIsBoundedToTwoHundredBytesInTheStatusError(t *testin
|
||||
require.ErrorAs(t, err, &se)
|
||||
assert.LessOrEqual(t, len(se.Snippet), 200, "a gateway's whole body must not become part of an error")
|
||||
}
|
||||
|
||||
// The language travels on the context (tapir#61); the request field is the only place it
|
||||
// takes effect, so these observe the request the gateway fake received.
|
||||
|
||||
func TestGateway_SendsLanguageSvWhenTheContextCarriesNoneAndForSwedish(t *testing.T) {
|
||||
for name, ctx := range map[string]context.Context{
|
||||
"no language in the context": context.Background(),
|
||||
"swedish": domain.WithLanguage(context.Background(), domain.LangSwedish),
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
var got seen
|
||||
srv := serve(t, 200, verboseJSON, &got)
|
||||
g := transcribe.NewGateway(srv.URL+"/v1", "k", "iguana/kb-whisper", srv.Client())
|
||||
|
||||
_, err := g.Transcribe(ctx, wavFile(t, "RIFF-synthetic-pcm"))
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "sv", got.fields["language"])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGateway_OmitsTheLanguageFieldForAnAutoContextSoTheEngineDetectsIt(t *testing.T) {
|
||||
var got seen
|
||||
srv := serve(t, 200, verboseJSON, &got)
|
||||
g := transcribe.NewGateway(srv.URL+"/v1", "k", "iguana/kb-whisper", srv.Client())
|
||||
|
||||
_, err := g.Transcribe(domain.WithLanguage(context.Background(), domain.LangAuto), wavFile(t, "RIFF-synthetic-pcm"))
|
||||
|
||||
require.NoError(t, err)
|
||||
_, present := got.fields["language"]
|
||||
assert.False(t, present, "an auto upload must not be forced to Swedish")
|
||||
assert.Equal(t, "iguana/kb-whisper", got.fields["model"], "the rest of the request is unchanged")
|
||||
}
|
||||
|
||||
func TestGateway_ALanguageOutsideTheClosedSetIsRefusedBeforeAnythingIsSent(t *testing.T) {
|
||||
var got seen
|
||||
srv := serve(t, 200, verboseJSON, &got)
|
||||
g := transcribe.NewGateway(srv.URL+"/v1", "k", "iguana/kb-whisper", srv.Client())
|
||||
|
||||
_, err := g.Transcribe(domain.WithLanguage(context.Background(), domain.Language("en")), wavFile(t, "RIFF-synthetic-pcm"))
|
||||
|
||||
require.Error(t, err)
|
||||
assert.Empty(t, got.method, "no request may reach the engine with a language the closed set does not hold")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user