Forward glossary provenance without transcript substitution
This commit is contained in:
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Record active glossary configuration without rewriting protocol transcript input.
|
||||||
|
|
||||||
- Reconciled the documented MVP with the validated Meeting Lab backend.
|
- Reconciled the documented MVP with the validated Meeting Lab backend.
|
||||||
- Selected `whisper.cpp` for transcription and made diarization optional.
|
- Selected `whisper.cpp` for transcription and made diarization optional.
|
||||||
- Defined the Python API, progress-event and Meeting Context integration
|
- Defined the Python API, progress-event and Meeting Context integration
|
||||||
|
|||||||
@@ -164,3 +164,8 @@ product work, not a current MVP requirement.
|
|||||||
- no automatic identity claims
|
- no automatic identity claims
|
||||||
- human review of generated protocols
|
- human review of generated protocols
|
||||||
- small modules and simple interfaces
|
- small modules and simple interfaces
|
||||||
|
|
||||||
|
Active glossary aliases are forwarded to Meeting Lab as provenance metadata.
|
||||||
|
Canonical terminology remains Meeting Context guidance; the exact protocol
|
||||||
|
transcript input and the raw Whisper/diarization artifacts are not rewritten.
|
||||||
|
`glossary_replacements` remains empty.
|
||||||
|
|||||||
@@ -229,3 +229,8 @@ transcription; Meeting Assistant does not duplicate audio conversion.
|
|||||||
|
|
||||||
See [Architecture](docs/architecture.md), [Project Knowledge](PROJECT_KNOWLEDGE.md),
|
See [Architecture](docs/architecture.md), [Project Knowledge](PROJECT_KNOWLEDGE.md),
|
||||||
[Roadmap](ROADMAP.md) and [ADR 0011](docs/adr/0011-use-meeting-lab-mvp-backend.md).
|
[Roadmap](ROADMAP.md) and [ADR 0011](docs/adr/0011-use-meeting-lab-mvp-backend.md).
|
||||||
|
|
||||||
|
Active glossary aliases are forwarded to Meeting Lab as provenance metadata.
|
||||||
|
Canonical terminology remains Meeting Context guidance; the exact protocol
|
||||||
|
transcript input and the raw Whisper/diarization artifacts are not rewritten.
|
||||||
|
`glossary_replacements` remains empty.
|
||||||
|
|||||||
@@ -355,6 +355,11 @@ def render_glossary_terms(entries: Iterable[GlossaryEntry]) -> list[str]:
|
|||||||
return rendered
|
return rendered
|
||||||
|
|
||||||
|
|
||||||
|
def glossary_alias_mapping(entries: Iterable[GlossaryEntry]) -> dict[str, str]:
|
||||||
|
"""Return explicit alias configuration for provenance, not substitution."""
|
||||||
|
return {alias: entry.canonical_term for entry in entries for alias in entry.aliases}
|
||||||
|
|
||||||
|
|
||||||
def _timestamp() -> str:
|
def _timestamp() -> str:
|
||||||
return datetime.now(UTC).isoformat(timespec="seconds")
|
return datetime.now(UTC).isoformat(timespec="seconds")
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ from uuid import uuid4
|
|||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from mka.application.config import AppSettings
|
from mka.application.config import AppSettings
|
||||||
from mka.application.glossary import GlossaryRepository, render_glossary_terms
|
from mka.application.glossary import (
|
||||||
|
GlossaryRepository,
|
||||||
|
glossary_alias_mapping,
|
||||||
|
render_glossary_terms,
|
||||||
|
)
|
||||||
from mka.application.performance import DEFAULT_PERFORMANCE_PROFILE, resolve_ollama_num_thread
|
from mka.application.performance import DEFAULT_PERFORMANCE_PROFILE, resolve_ollama_num_thread
|
||||||
|
|
||||||
STAGES = ("preparing", "transcription", "diarization", "protocol_generation")
|
STAGES = ("preparing", "transcription", "diarization", "protocol_generation")
|
||||||
@@ -231,6 +235,7 @@ class MeetingProcessingService:
|
|||||||
"model": self.settings.protocol_model,
|
"model": self.settings.protocol_model,
|
||||||
"ollama_endpoint": self.settings.ollama_endpoint,
|
"ollama_endpoint": self.settings.ollama_endpoint,
|
||||||
"protocol_num_ctx": self.settings.protocol_num_ctx,
|
"protocol_num_ctx": self.settings.protocol_num_ctx,
|
||||||
|
"glossary_aliases": glossary_alias_mapping(self.glossary.list(active_only=True)),
|
||||||
"protocol_num_thread": resolve_ollama_num_thread(options.performance_profile),
|
"protocol_num_thread": resolve_ollama_num_thread(options.performance_profile),
|
||||||
"protocol_safe_input_token_budget": (
|
"protocol_safe_input_token_budget": (
|
||||||
self.settings.protocol_safe_input_token_budget
|
self.settings.protocol_safe_input_token_budget
|
||||||
@@ -405,6 +410,7 @@ class MeetingProcessingService:
|
|||||||
model=self.settings.protocol_model,
|
model=self.settings.protocol_model,
|
||||||
ollama_endpoint=self.settings.ollama_endpoint,
|
ollama_endpoint=self.settings.ollama_endpoint,
|
||||||
protocol_num_ctx=self.settings.protocol_num_ctx,
|
protocol_num_ctx=self.settings.protocol_num_ctx,
|
||||||
|
glossary_aliases=glossary_alias_mapping(self.glossary.list(active_only=True)),
|
||||||
protocol_num_thread=resolve_ollama_num_thread(performance_profile),
|
protocol_num_thread=resolve_ollama_num_thread(performance_profile),
|
||||||
protocol_safe_input_token_budget=(self.settings.protocol_safe_input_token_budget),
|
protocol_safe_input_token_budget=(self.settings.protocol_safe_input_token_budget),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -512,6 +512,7 @@ def test_protocol_only_regeneration_persists_mappings_without_rewriting_transcri
|
|||||||
"SPEAKER_00": "martin"
|
"SPEAKER_00": "martin"
|
||||||
}
|
}
|
||||||
assert gateway.regeneration["options"]["protocol_num_ctx"] == 32_768
|
assert gateway.regeneration["options"]["protocol_num_ctx"] == 32_768
|
||||||
|
assert gateway.regeneration["options"]["glossary_aliases"] == {"Enlyse": "ENLYZE"}
|
||||||
assert events[0].stage == "protocol_generation"
|
assert events[0].stage == "protocol_generation"
|
||||||
assert source.read_bytes() == original_source
|
assert source.read_bytes() == original_source
|
||||||
|
|
||||||
@@ -608,3 +609,17 @@ def test_protocol_regeneration_propagates_explicit_profile(tmp_path: Path) -> No
|
|||||||
|
|
||||||
assert gateway.regeneration is not None
|
assert gateway.regeneration is not None
|
||||||
assert gateway.regeneration["options"]["protocol_num_thread"] == 16
|
assert gateway.regeneration["options"]["protocol_num_thread"] == 16
|
||||||
|
|
||||||
|
|
||||||
|
def test_process_passes_only_active_explicit_glossary_aliases(tmp_path: Path) -> None:
|
||||||
|
service, gateway = make_service(tmp_path)
|
||||||
|
service.glossary.create("Luminy", "product", aliases=("Lumini",))
|
||||||
|
inactive = service.glossary.create("PBAT", "acronym", aliases=("PBRT",))
|
||||||
|
service.glossary.set_active(inactive.id, False)
|
||||||
|
audio = tmp_path / "meeting.wav"
|
||||||
|
audio.write_bytes(b"audio")
|
||||||
|
|
||||||
|
service.process(audio, meeting(), participants(), ProcessingOptions())
|
||||||
|
|
||||||
|
assert gateway.config_values is not None
|
||||||
|
assert gateway.config_values["glossary_aliases"] == {"Lumini": "Luminy"}
|
||||||
|
|||||||
Reference in New Issue
Block a user