mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-12 22:14:37 +00:00
Phase 1 of the TTS params/layout/agent-override plan.
Capability schema:
- `ParamSchema.Group` field (`"basic"` default, `"advanced"` when set).
- Tag existing advanced params across openai/elevenlabs/minimax/gemini.
Gemini:
- Expose `temperature` (basic, 0.0–2.0, default 1.0, subtle-effect note),
`seed`, `presencePenalty`, `frequencyPenalty` (advanced, experimental).
- Merge into `generationConfig` via explicit-presence resolvers so
nil-params bodies stay byte-equivalent.
ElevenLabs:
- `output_format` enum (27 variants, default `mp3_44100_128`, advanced).
- `FormatMeta` lookup drives SynthResult MIME + extension.
- URL built via `net/url.Values.Encode()`; regex pre-validation for
`output_format` (`^[a-z0-9_]+$`) and `language_code`
(`^[a-z]{2,3}(-[A-Z]{2})?$`) blocks query-string injection.
- Telegram opus contract preserved: `opts.Format=="opus"` forces
`audio/ogg; codecs=opus` regardless of user-set `output_format`.
MiniMax:
- `language_boost` (basic enum), `subtitle_enable` (basic bool),
`pronunciation_dict` (advanced text, 8KB cap, wrapped as
`{"tone":[...]}`). Parse failure logs length only + omits.
Validation:
- `audio.ValidateParams` enforces Min/Max/Enum + rejects unknown keys.
- Wired into `/v1/tts/synthesize` and `/v1/tts/config` write paths.
- `loadParamsBlob` capped at 16KB.
- i18n keys `MsgTtsParamOutOfRange`, `MsgTtsParamInvalidJSON`,
`MsgTtsParamUnknownKey` added to en/vi/zh catalogs.
Tests:
- Golden `testdata/default_body.golden.json` per provider (gemini,
elevenlabs, minimax, openai) checked in; invariant tests diff
against file instead of self-referential capture.
- Round-trip tests for each new param + Telegram opus contract +
URL-injection attempts.
83 lines
2.6 KiB
Go
83 lines
2.6 KiB
Go
package gemini
|
||
|
||
import "github.com/nextlevelbuilder/goclaw/internal/audio"
|
||
|
||
var (
|
||
geminiTempMin = 0.0
|
||
geminiTempMax = 2.0
|
||
geminiTempStep = 0.01
|
||
|
||
geminiPenaltyMin = -2.0
|
||
geminiPenaltyMax = 2.0
|
||
geminiPenaltyStep = 0.01
|
||
)
|
||
|
||
// geminiParams is the enriched param schema for Gemini TTS.
|
||
// All params have nil Default so they are omitted from the request body
|
||
// when not explicitly set, preserving characterization byte-equivalence.
|
||
//
|
||
// Tagging:
|
||
// - temperature: basic (Group="")
|
||
// - seed, presencePenalty, frequencyPenalty: advanced (Group="advanced")
|
||
var geminiParams = []audio.ParamSchema{
|
||
{
|
||
Key: "temperature",
|
||
Type: audio.ParamTypeRange,
|
||
Label: "Temperature",
|
||
// Finding #14: note subtle effect on TTS; primary expressiveness via audio tags.
|
||
Description: "Sampling temperature (0.0–2.0, default 1.0). Effect is subtle on TTS — primary expressiveness comes from audio tags inserted in the text.",
|
||
Default: nil, // omit from body when not set; API default is 1.0
|
||
Min: &geminiTempMin,
|
||
Max: &geminiTempMax,
|
||
Step: &geminiTempStep,
|
||
Group: "", // basic
|
||
},
|
||
{
|
||
Key: "seed",
|
||
Type: audio.ParamTypeInteger,
|
||
Label: "Seed",
|
||
Description: "Deterministic seed for reproducible output. Advanced.",
|
||
Default: nil,
|
||
Group: "advanced",
|
||
},
|
||
{
|
||
Key: "presencePenalty",
|
||
Type: audio.ParamTypeRange,
|
||
Label: "Presence Penalty",
|
||
Description: "Presence penalty (-2.0–2.0). Experimental — effect on TTS is not well-characterised. Advanced.",
|
||
Default: nil,
|
||
Min: &geminiPenaltyMin,
|
||
Max: &geminiPenaltyMax,
|
||
Step: &geminiPenaltyStep,
|
||
Group: "advanced",
|
||
},
|
||
{
|
||
Key: "frequencyPenalty",
|
||
Type: audio.ParamTypeRange,
|
||
Label: "Frequency Penalty",
|
||
Description: "Frequency penalty (-2.0–2.0). Experimental — effect on TTS is not well-characterised. Advanced.",
|
||
Default: nil,
|
||
Min: &geminiPenaltyMin,
|
||
Max: &geminiPenaltyMax,
|
||
Step: &geminiPenaltyStep,
|
||
Group: "advanced",
|
||
},
|
||
}
|
||
|
||
// Capabilities returns the static capability schema for the Gemini TTS provider.
|
||
// CustomFeatures drives frontend custom slot rendering in Phase C.
|
||
func (p *Provider) Capabilities() audio.ProviderCapabilities {
|
||
return audio.ProviderCapabilities{
|
||
Provider: "gemini",
|
||
DisplayName: "Google Gemini TTS",
|
||
RequiresAPIKey: true,
|
||
Models: geminiModels,
|
||
Voices: geminiVoices,
|
||
Params: geminiParams,
|
||
CustomFeatures: map[string]any{
|
||
"multi_speaker": true,
|
||
"audio_tags": true,
|
||
},
|
||
}
|
||
}
|