Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
Sergey
bc673e7c24
docs(readme): fix custom STT endpoint section (#49)
Some checks failed
CI / check (push) Successful in 1m41s
Deploy / build (push) Failing after 5s
## Что сделано

- EN и RU секции «Custom STT Endpoint» обновлены: nginx-конфиг заменён
на pass-through вариант без префикса:
  ```nginx
  location / {
      proxy_pass https://api.groq.com:443;
      proxy_set_header Host api.groq.com;
  }
  ```
- Пример endpoint теперь
`https://your-domain.com/openai/v1/audio/transcriptions` (без `/groq`) —
совпадает с реальной настройкой сервера (whisper.slaid098.dev).
- Добавлена заметка в обе секции: префикс пути не нужен, если домен
выделен только под Groq; `/groq`-вариант остаётся валидным для
мульти-прокси доменов (`location /groq/` с trailing slash срезает
префикс).

## Почему

README описывал конфиг с префиксом `/groq`, который не совпадает с
реальной настройкой. `proxy_pass` без trailing slash передаёт URI как
есть, поэтому на выделенном домене префикс лишний и только усложняет
настройку. Документация должна совпадать с реальным рабочим сервером.

## Watch out

- Только README.md (EN + RU секции). Код, тесты, версия не тронуты —
bump не требуется по AGENTS.md.

## Pending

—

Closes #48

Closes #48

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-08-06 11:10:06 +03:00
Sergey
b8040f6cd3
fix(transcription): empty whisperPrompt default to stop English bias (#47)
## Что сделано

- `DEFAULTS.whisperPrompt` изменён с 107-символьного английского списка
терминов на пустую строку (`src/config.ts:8`). Английский промпт уводил
русский аудио в английский (особенно на turbo) — нарушает документацию
Groq: «Use the same language as the language of the audio file».
- `tests/config.test.ts` — 2 устаревших теста (`non-empty
whisperPrompt`, `under 120 characters`) заменены на 1: `should have
empty whisperPrompt by default`.
- Version bump 1.0.4 → 1.0.5 в `vite.config.ts:11` и `package.json:3`.
- ADR-0007 (`docs/decisions/0007-pr-46-empty-whisper-prompt.md`) —
фиксирует решение, контекст (PR #43 + баг), последствия (`buildFormData`
falsy-check), альтернативы (двуязычный промпт, смена модели — обе
отвергнуты).
- README — секция troubleshooting «Wrong Language (English instead of
Russian)» добавлена в EN и RU секции после температурного блока.
Инструкция очистить Whisper Prompt через меню Tampermonkey.

## Почему

PR #43 добавил английский biasing-промпт для технических терминов. На
практике английский промпт + русский аудио = модель возвращает
английский текст, перебивая явный `language=ru`. Пользователь подтвердил
баг на turbo. Параметр `prompt` Whisper — это seed-контекст декодера,
модель стремится продолжить его язык. Пустой default = чистый
auto-detect без biasing. Поле и menu command остаются для юзеров с
узкопрофильной терминологией.

## Watch out

- **Обратная совместимость**: существующие юзеры со старым
107-символьным значением в `GM_getValue("whisperPrompt")` сохраняют его
— новый default применяется только к свежим установкам и к тем, кто
очистил поле через `Set Whisper Prompt`. Миграции нет намеренно (не
ломаем сохранённые настройки).
- `buildFormData` использует falsy-check `if (config.whisperPrompt)` —
пустая строка не отправляет поле `prompt` в Groq API вообще.
- `transcribe.test.ts` использует mock `whisperPrompt: "Software
development discussion."` — валидный mock для тестирования
prompt-передачи, НЕ тронут (не путать с DEFAULTS).
- `DEFAULTS.model` (`whisper-large-v3`), `DEFAULTS.language` (`""`),
`DEFAULTS.temperature` (`0`), `DEFAULTS.endpoint` — не менялись. Смена
модели на turbo была альтернативой, отвергнута (v3 лучше для русского,
баг в промпте не в модели).
- Touchpoints ровно 7: `src/config.ts`, `tests/config.test.ts`,
`vite.config.ts`, `package.json`, `docs/decisions/0007-*.md` (новый),
`README.md` (2 вставки EN+RU). `src/transcribe.ts` и остальные src-файлы
не тронуты.

## Pending

- CI на push-ветке (vitest, biome, tsc, knip) — все зелёные локально
(55/55 tests, 22 файла biome-clean, tsc чист, knip чист).
- После merge — ADR-0007 ссылается на PR #46 (номер уже известен из
issue).

Closes #46

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-08-04 15:13:01 +03:00
6 changed files with 83 additions and 16 deletions

View file

@ -49,18 +49,30 @@ Groq may block direct requests from some networks. Point the script at your own
1. Deploy an nginx reverse proxy that forwards to `api.groq.com`: 1. Deploy an nginx reverse proxy that forwards to `api.groq.com`:
```nginx ```nginx
location /groq/ { location / {
proxy_pass https://api.groq.com/; proxy_pass https://api.groq.com:443;
proxy_set_header Host api.groq.com; proxy_set_header Host api.groq.com;
} }
``` ```
2. Tampermonkey menu → **Set STT Endpoint** → paste `https://your-domain.com/groq/openai/v1/audio/transcriptions` 2. Tampermonkey menu → **Set STT Endpoint** → paste `https://your-domain.com/openai/v1/audio/transcriptions`
3. Requests now go through your proxy. The userscript metadata uses `@connect *`, so any domain is allowed. 3. Requests now go through your proxy. The userscript metadata uses `@connect *`, so any domain is allowed.
A path prefix is not needed if the domain is dedicated to Groq. The `/groq` variant stays valid for multi-proxy domains — `location /groq/` with a trailing slash strips the prefix.
### 🌡️ Temperature ### 🌡️ Temperature
Whisper may hallucinate on silence/noise. **Set Temperature** (default `0` = deterministic, range `0``1`) reduces hallucinations. Whisper may hallucinate on silence/noise. **Set Temperature** (default `0` = deterministic, range `0``1`) reduces hallucinations.
### 🌐 Wrong Language (English instead of Russian)
If the model returns English text for Russian audio, clear the Whisper Prompt:
1. Open Tampermonkey/Violentmonkey menu → **Set Whisper Prompt**
2. Leave the field empty (delete all text)
3. Confirm
The prompt biases the model toward the prompt's language. An English prompt with Russian audio causes the model to output English. The prompt should match the audio language (or be empty for auto-detect).
--- ---
## 🇷🇺 Русский ## 🇷🇺 Русский
@ -101,18 +113,30 @@ Groq может блокировать прямые запросы из неко
1. Разверни nginx reverse proxy, который форвардит на `api.groq.com`: 1. Разверни nginx reverse proxy, который форвардит на `api.groq.com`:
```nginx ```nginx
location /groq/ { location / {
proxy_pass https://api.groq.com/; proxy_pass https://api.groq.com:443;
proxy_set_header Host api.groq.com; proxy_set_header Host api.groq.com;
} }
``` ```
2. Меню Tampermonkey → **Set STT Endpoint** → вставь `https://your-domain.com/groq/openai/v1/audio/transcriptions` 2. Меню Tampermonkey → **Set STT Endpoint** → вставь `https://your-domain.com/openai/v1/audio/transcriptions`
3. Запросы пойдут через твой прокси. Метаблок юзерскрипта использует `@connect *`, поэтому разрешён любой домен. 3. Запросы пойдут через твой прокси. Метаблок юзерскрипта использует `@connect *`, поэтому разрешён любой домен.
Префикс пути не нужен, если домен выделен только под Groq. `/groq`-вариант остаётся валидным для мульти-прокси доменов — `location /groq/` с trailing slash срезает префикс.
### 🌡️ Temperature ### 🌡️ Temperature
Whisper может галлюцинировать на тишине/шуме. **Set Temperature** (по умолчанию `0` = детерминированный вывод, диапазон `0``1`) снижает галлюцинации. Whisper может галлюцинировать на тишине/шуме. **Set Temperature** (по умолчанию `0` = детерминированный вывод, диапазон `0``1`) снижает галлюцинации.
### 🌐 Неправильный язык (английский вместо русского)
Если модель возвращает английский текст для русской речи, очистите Whisper Prompt:
1. Откройте меню Tampermonkey/Violentmonkey → **Set Whisper Prompt**
2. Оставьте поле пустым (удалите весь текст)
3. Подтвердите
Промпт смещает модель к языку промпта. Английский промпт с русским аудио заставляет модель выводить английский. Промпт должен совпадать с языком аудио (или быть пустым для автоопределения).
--- ---
## 💬 Support and contacts / Поддержка и контакты ## 💬 Support and contacts / Поддержка и контакты

View file

@ -0,0 +1,48 @@
# ADR 0007: Empty whisperPrompt default (PR #46)
- **Date**: 2026-08-04
- **PR**: 46
- **Issue**: #46
## Статус
Accepted.
## Контекст
PR #43 добавил `DEFAULTS.whisperPrompt` — 107-символьный английский список терминов (`opencode, voice, dictation, transcribe, command, terminal, commit, branch, pull, push, merge, issue, prompt`). Целью было biasing-смещение модели в сторону технической терминологии userscript-а.
Документация Groq для параметра `prompt` (Whisper API) явно указывает: «Use the same language as the language of the audio file». Параметр `prompt` — это не системный промпт, а seed-контекст для декодера: модель стремится продолжить стиль и язык промпта в транскрипции.
Практический баг: английский промпт + русский аудио = модель уводит транскрипт в английский. Особенно заметно на `whisper-large-v3-turbo` (turbo более чувствителен к prompt biasing). Пользователь подтвердил: `language=ru` + turbo всё равно возвращает английский текст, потому что английский промпт перебивает явный `language` параметр.
## Решение
**`DEFAULTS.whisperPrompt = ""` (пустая строка).**
Поле `whisperPrompt` в `AppConfig` остаётся. Menu command `Set Whisper Prompt` (`registerMenuCommands`) остаётся — пользователи с узкопрофильной терминологией (медицина, право, конкретный стек) могут задать свой промпт на нужном языке. Меняется только default: пустая строка вместо английского biasing-промпта.
## Последствия
- `buildFormData` в `src/transcribe.ts` использует falsy-check `if (config.whisperPrompt)` — пустая строка не отправляет поле `prompt` в Groq API вообще. Модель работает в чистом auto-detect режиме без prompt biasing.
- Обратная совместимость: существующие юзеры, установившие скрипт в версии 1.0.4 (PR #43) и не менявшие `whisperPrompt` через меню, имеют в `GM_getValue("whisperPrompt")` старое 107-символьное значение — оно сохранится и продолжит отправляться. Новый default применяется только к свежим установкам и к юзерам, очистившим поле через `Set Whisper Prompt`.
- README обновлён секцией troubleshooting «Wrong Language» (EN+RU) — инструкция очистить Whisper Prompt через меню.
- Версия bumped 1.0.4 → 1.0.5 (vite.config.ts + package.json).
## Альтернативы
### 1. Двуязычный промпт (английский + русский термины)
- **Плюс**: biasing в обе стороны.
- **Минус**: усложнение. Промпт нужно поддерживать при добавлении новых языков (сейчас `language` поддерживает `ru`/`en`/`auto`). При `auto` модель может растеряться от двуязычного промпта. Отвергнуто.
### 2. Смена модели на turbo по умолчанию
- **Плюс**: turbo быстрее.
- **Минус**: баг был в промпте, не в модели. `whisper-large-v3` лучше для русского (точность выше, turbo оптимизирован под английский). Смена модели не решила бы проблему английского biasing-а. Отвергнуто.
## Источники
- `src/config.ts``DEFAULTS.whisperPrompt` до/после
- `src/transcribe.ts``buildFormData` falsy-check `if (config.whisperPrompt)`
- Groq Whisper API docs — `prompt` parameter: «Use the same language as the language of the audio file»
- PR #43 — добавление `DEFAULTS.whisperPrompt` (107 символов)
- Issue: #46

View file

@ -1,6 +1,6 @@
{ {
"name": "opencode-voice-dictation", "name": "opencode-voice-dictation",
"version": "1.0.4", "version": "1.0.5",
"private": true, "private": true,
"type": "module", "type": "module",
"engines": { "engines": {

View file

@ -5,8 +5,7 @@ export const DEFAULTS: AppConfig = {
groqApiKey: "", groqApiKey: "",
model: "whisper-large-v3", model: "whisper-large-v3",
language: "", language: "",
whisperPrompt: whisperPrompt: "",
"opencode, voice, dictation, transcribe, command, terminal, commit, branch, pull, push, merge, issue, prompt",
endpoint: "https://api.groq.com/openai/v1/audio/transcriptions", endpoint: "https://api.groq.com/openai/v1/audio/transcriptions",
temperature: 0, temperature: 0,
autoSubmit: false, autoSubmit: false,

View file

@ -26,12 +26,8 @@ describe("DEFAULTS", () => {
expect(DEFAULTS.language).toBe(""); expect(DEFAULTS.language).toBe("");
}); });
it("should have non-empty whisperPrompt", () => { it("should have empty whisperPrompt by default", () => {
expect(DEFAULTS.whisperPrompt.length).toBeGreaterThan(50); expect(DEFAULTS.whisperPrompt).toBe("");
});
it("should have whisperPrompt under 120 characters (terms only, no sentences)", () => {
expect(DEFAULTS.whisperPrompt.length).toBeLessThan(120);
}); });
it("should have autoSubmit disabled by default", () => { it("should have autoSubmit disabled by default", () => {

View file

@ -8,7 +8,7 @@ export default defineConfig({
userscript: { userscript: {
name: "OpenCode Voice Dictation", name: "OpenCode Voice Dictation",
namespace: "https://github.com/slaid098/opencode-voice-dictation", namespace: "https://github.com/slaid098/opencode-voice-dictation",
version: "1.0.4", version: "1.0.5",
description: description:
"Voice dictation for OpenCode web using Whisper (Groq API) - works on PC and mobile", "Voice dictation for OpenCode web using Whisper (Groq API) - works on PC and mobile",
author: "slaid098", author: "slaid098",