lazier

personal summarizer
Log | Files | Refs | README

commit 739d31d59b2bcafd851301b9ec303d8dd421858b
parent 93d419ec0765d499ad28e463bbc2b034bdbcbc39
Author: Pablo Murad <pblmrd@gmail.com>
Date:   Sat,  9 May 2026 22:27:31 -0300

remodelation

Diffstat:
M.env.example | 2+-
MREADME.md | 7+++----
Mlazier/api/routes.py | 8--------
Mlazier/cli.py | 13-------------
Mlazier/core/processing.py | 26+++++---------------------
Mlazier/web/templates/index.html | 12------------
Mtests/test_api.py | 3+--
7 files changed, 10 insertions(+), 61 deletions(-)

diff --git a/.env.example b/.env.example @@ -39,7 +39,7 @@ OPENAI_API_KEY= # Preset global e sumarizacao hierarquica (textos longos) # --------------------------------------------------------------------------- -# Preset padrao quando nao se envia quality_preset na API/Web: economico | equilibrado | maximo. +# Preset global (unico controlo): economico | equilibrado | maximo. # Mapeia defaults de chat, transcricao e reasoning (sobrescritos por OPENAI_* quando definidos). # LAZIER_QUALITY_PRESET=equilibrado diff --git a/README.md b/README.md @@ -34,7 +34,7 @@ Defaults seguros já vêm configurados; sobrescreva apenas se quiser mudar. | `OPENAI_ENABLE_SMART_SUMMARY` | `true` | Liga/desliga o sumário estruturado (TL;DR, pontos-chave, decisões, ações, tópicos, citações, perguntas em aberto). Quando `false`, mantém o sumário textual legado. | | `OPENAI_ENABLE_CHAPTERS` | `true` | Liga/desliga geração de capítulos com timestamps em áudio/vídeo. | | `OPENAI_REASONING_EFFORT` | `medium` | Esforço de raciocínio para modelos da família `gpt-5`/`o-series`. Valores: `minimal`, `low`, `medium`, `high`. | -| `LAZIER_QUALITY_PRESET` | `equilibrado` | Preset global `economico` / `equilibrado` / `maximo` → defaults de chat, transcrição e `reasoning` (sobrescritos por `OPENAI_*` quando definidos). Na Web/API pode enviar-se `quality_preset` por pedido. | +| `LAZIER_QUALITY_PRESET` | `equilibrado` | Preset global `economico` / `equilibrado` / `maximo` → defaults de chat, transcrição e `reasoning` (sobrescritos por `OPENAI_*` quando definidos). Defina apenas no `.env`; não há seleção na WebGUI nem campo por pedido na API. | | `LAZIER_SUMMARY_HIERARCHICAL` | `true` | Acima de `LAZIER_SUMMARY_DIRECT_MAX_CHARS`, o sumário inteligente usa map-reduce com chunks e overlap em vez de um único passe sobre o texto completo. | | `LAZIER_SUMMARY_DIRECT_MAX_CHARS` | `32000` | Limiar (caracteres) para ativar sumarização hierárquica. | | `LAZIER_SUMMARY_MAP_CHUNK_CHARS` | `14000` | Tamanho alvo de cada chunk no map. | @@ -102,8 +102,6 @@ lazier transcribe "https://www.youtube.com/watch?v=VIDEO_ID" lazier summarize document.pdf lazier summarize "https://example.com/artigo" --format md lazier summarize aula.mp3 --gpt-model gpt-5 --reasoning high -lazier summarize documento.pdf --quality-preset economico - # Desligar features novas explicitamente lazier summarize aula.mp3 --no-smart --no-chapters @@ -121,7 +119,8 @@ Flags principais: - `--smart/--no-smart` força ligar/desligar o sumário estruturado. - `--chapters/--no-chapters` força ligar/desligar capítulos com timestamps. - `--reasoning {minimal,low,medium,high}` ajusta o esforço de raciocínio para modelos `gpt-5`/`o-series`. -- `--quality-preset {economico,equilibrado,maximo}` aplica o pacote de modelos e reasoning desse preset só nesse comando (equivalente ao campo da WebGUI). + +O pacote custo/qualidade (`economico` / `equilibrado` / `maximo`) vem só de `LAZIER_QUALITY_PRESET` no `.env` (`lazier config` mostra o valor atual). ### WebGUI diff --git a/lazier/api/routes.py b/lazier/api/routes.py @@ -42,7 +42,6 @@ class ProcessRequest(BaseModel): summarize: Optional[bool] = None chat_model: Optional[str] = None transcribe_model: Optional[str] = None - quality_preset: Optional[str] = None smart: Optional[bool] = None chapters: Optional[bool] = None @@ -103,15 +102,12 @@ def _build_overrides( transcribe_model: Optional[str] = None, smart: Optional[bool] = None, chapters: Optional[bool] = None, - quality_preset: Optional[str] = None, ) -> dict: overrides: dict = {} if chat_model: overrides["chat_model"] = chat_model if transcribe_model: overrides["transcribe_model"] = transcribe_model - if quality_preset: - overrides["quality_preset"] = quality_preset.strip().lower() if smart is not None: overrides["smart"] = smart if chapters is not None: @@ -175,7 +171,6 @@ def _process_job(job_id: str) -> None: gpt_model=overrides.get("chat_model"), use_smart_summary=overrides.get("smart"), use_chapters=overrides.get("chapters"), - quality_preset=overrides.get("quality_preset"), trace_job_id=job_id, run_id=job_id, source_name=job.get("source_name"), @@ -294,7 +289,6 @@ async def upload_files( summarize: Optional[bool] = Form(None), chat_model: Optional[str] = Form(None), transcribe_model: Optional[str] = Form(None), - quality_preset: Optional[str] = Form(None), smart: Optional[bool] = Form(None), chapters: Optional[bool] = Form(None), ): @@ -306,7 +300,6 @@ async def upload_files( transcribe_model=transcribe_model, smart=smart, chapters=chapters, - quality_preset=quality_preset, ) jobs = [] @@ -363,7 +356,6 @@ async def process_url(request: ProcessRequest, background_tasks: BackgroundTasks transcribe_model=request.transcribe_model, smart=request.smart, chapters=request.chapters, - quality_preset=request.quality_preset, ) job = _create_job( diff --git a/lazier/cli.py b/lazier/cli.py @@ -50,7 +50,6 @@ def _run_mode( smart: Optional[bool] = None, chapters: Optional[bool] = None, reasoning: Optional[str] = None, - quality_preset: Optional[str] = None, ): if reasoning: os.environ["OPENAI_REASONING_EFFORT"] = reasoning @@ -91,7 +90,6 @@ def _run_mode( gpt_model=gpt_model, use_smart_summary=smart, use_chapters=chapters, - quality_preset=quality_preset, output_path=output, run_id=str(uuid.uuid4()), source_name=Path(input_path).name if not input_path.startswith(("http://", "https://")) else input_path, @@ -166,13 +164,6 @@ def _model_options(func): default=None, help="Modelo de transcricao (default: OPENAI_TRANSCRIBE_MODEL ou gpt-4o-mini-transcribe)", )(func) - func = click.option( - "--quality-preset", - "quality_preset", - type=click.Choice(["economico", "equilibrado", "maximo"]), - default=None, - help="Preset custo/qualidade para este comando (modelos + reasoning). Sobrescreve LAZIER_QUALITY_PRESET.", - )(func) return func @@ -190,7 +181,6 @@ def transcribe( smart_flag: Optional[bool], chapters_flag: Optional[bool], reasoning: Optional[str], - quality_preset: Optional[str], ): """Transcreve ou converte o conteudo para portugues.""" _run_mode( @@ -203,7 +193,6 @@ def transcribe( smart=smart_flag, chapters=chapters_flag, reasoning=reasoning, - quality_preset=quality_preset, ) @@ -221,7 +210,6 @@ def summarize( smart_flag: Optional[bool], chapters_flag: Optional[bool], reasoning: Optional[str], - quality_preset: Optional[str], ): """Gera um sumario em portugues do conteudo informado.""" _run_mode( @@ -234,7 +222,6 @@ def summarize( smart=smart_flag, chapters=chapters_flag, reasoning=reasoning, - quality_preset=quality_preset, ) diff --git a/lazier/core/processing.py b/lazier/core/processing.py @@ -23,7 +23,7 @@ from typing import Any, Callable, Dict, List, Optional, Tuple from .cache import calculate_file_hash, calculate_string_hash, calculate_url_hash, get_cache_manager from .chapters import build_chapters -from .config import VALID_REASONING_EFFORTS, get_model_config, get_preset_model_defaults +from .config import get_model_config from .content_type import detect_content_type from .exceptions import MusicContentError from .jobs import build_job_artifact_path, get_outputs_root @@ -85,30 +85,16 @@ def _resolve_runtime( gpt_model: Optional[str], use_smart_summary: Optional[bool], use_chapters: Optional[bool], - *, - quality_preset: Optional[str] = None, ) -> Dict[str, Any]: config = get_model_config() - if quality_preset: - pd = get_preset_model_defaults(quality_preset) - transcribe_model = model or pd["transcribe_model"] - chat_model = gpt_model or pd["chat_model"] - reasoning_effort = pd["reasoning_effort"] - if reasoning_effort not in VALID_REASONING_EFFORTS: - reasoning_effort = config.reasoning_effort - else: - transcribe_model = model or config.transcribe_model - chat_model = gpt_model or config.chat_model - reasoning_effort = config.reasoning_effort - return { - "transcribe_model": transcribe_model, + "transcribe_model": model or config.transcribe_model, "transcribe_timestamps_model": config.transcribe_timestamps_model, - "chat_model": chat_model, + "chat_model": gpt_model or config.chat_model, "smart_summary": config.enable_smart_summary if use_smart_summary is None else use_smart_summary, "chapters_enabled": config.enable_chapters if use_chapters is None else use_chapters, - "reasoning_effort": reasoning_effort, - "quality_preset": quality_preset or config.quality_preset, + "reasoning_effort": config.reasoning_effort, + "quality_preset": config.quality_preset, } @@ -344,7 +330,6 @@ def process_source( gpt_model: Optional[str] = None, use_smart_summary: Optional[bool] = None, use_chapters: Optional[bool] = None, - quality_preset: Optional[str] = None, trace_job_id: Optional[str] = None, output_path: Optional[str] = None, output_root: Optional[Path] = None, @@ -363,7 +348,6 @@ def process_source( gpt_model, use_smart_summary, use_chapters, - quality_preset=quality_preset, ) t_pipeline = time.perf_counter() _notify(progress_callback, 5, "processing", "Validando entrada...") diff --git a/lazier/web/templates/index.html b/lazier/web/templates/index.html @@ -347,15 +347,6 @@ <label for="formatSelect">Formato</label> <select id="formatSelect"><option value="docx">DOCX</option><option value="txt">TXT</option><option value="md">Markdown</option><option value="json">JSON</option><option value="pdf">PDF</option></select> </div> - <div class="field"> - <label for="presetSelect">Qualidade</label> - <select id="presetSelect"> - <option value="">Predefinição (.env)</option> - <option value="economico">Económico</option> - <option value="equilibrado">Equilibrado</option> - <option value="maximo">Máximo</option> - </select> - </div> <button class="btn" id="processBtn" onclick="processFiles()">Processar</button> </div> </div> @@ -453,14 +444,12 @@ async function processFiles() { const button = document.getElementById('processBtn'); const format = document.getElementById('formatSelect').value; - const preset = document.getElementById('presetSelect').value; const url = document.getElementById('urlInput').value.trim(); button.disabled = true; button.textContent = 'A processar…'; try { if (url) { const payload = { url, format, mode: processingMode }; - if (preset) payload.quality_preset = preset; const response = await fetch('/api/process', { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(payload), credentials:'include' }); const data = await response.json(); if (!response.ok) throw new Error(data.detail || 'Falha ao processar URL'); @@ -471,7 +460,6 @@ selectedFiles.forEach((file) => formData.append('files', file)); formData.append('format', format); formData.append('mode', processingMode); - if (preset) formData.append('quality_preset', preset); const response = await fetch('/api/upload', { method:'POST', body:formData, credentials:'include' }); const data = await response.json(); if (!response.ok) throw new Error(data.detail || 'Falha ao enviar ficheiros'); diff --git a/tests/test_api.py b/tests/test_api.py @@ -170,7 +170,6 @@ class ApiTests(unittest.TestCase): "mode": "summarize", "chat_model": "gpt-5", "transcribe_model": "gpt-4o-transcribe", - "quality_preset": "economico", "smart": True, "chapters": True, }, @@ -182,7 +181,7 @@ class ApiTests(unittest.TestCase): kwargs = mock_process.call_args.kwargs self.assertEqual(kwargs.get("gpt_model"), "gpt-5") self.assertEqual(kwargs.get("model"), "gpt-4o-transcribe") - self.assertEqual(kwargs.get("quality_preset"), "economico") + self.assertIsNone(kwargs.get("quality_preset")) self.assertEqual(kwargs.get("trace_job_id"), job_id) self.assertTrue(kwargs.get("use_smart_summary")) self.assertTrue(kwargs.get("use_chapters"))