Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions .cursorignore

This file was deleted.

4 changes: 2 additions & 2 deletions Dockerfile → .devops/openvino.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
# - battlemage : Battlemage Intel GPU path
#
# Build examples:
# docker build --target standard -t {imagename}:dev .
# docker build --target battlemage -t {imagename}-battlemage:dev .
# docker build --target standard -t {imagename}:dev -f .devops/openvino.Dockerfile .
# docker build --target battlemage -t {imagename}-battlemage:dev -f .devops/openvino.Dockerfile .
# ============================================================================

# ============================================================================
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/build-container-image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ jobs:
with:
context: .
target: standard
file: .devops/openvino.Dockerfile
push: true
tags: ${{ steps.meta-standard.outputs.tags }}
labels: ${{ steps.meta-standard.outputs.labels }}
Expand All @@ -80,6 +81,7 @@ jobs:
with:
context: .
target: battlemage
file: .devops/openvino.Dockerfile
push: true
tags: ${{ steps.meta-battlemage.outputs.tags }}
labels: ${{ steps.meta-battlemage.outputs.labels }}
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
OpenArc uses bleeding edge libraries and APIs you may not be familair with. When working through a task, use the deepwiki mcp server to get *contextual* information, and the command line to investigate python surfaces. Prefer the command line.
OpenArc uses bleeding edge libraries and APIs you may not be familair with. Ask the user for access to reference matieral.



Expand Down
125 changes: 0 additions & 125 deletions benchmark/context_overflow.py

This file was deleted.

57 changes: 57 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
server:
port:


# comma seperated list of model_name to load on startup

# from env
startup_models : ${OPENRARC_AUTOLOAD_MODELS}


models:
qwen35-08b:
engine: ovgenai
model_type: llm
model_path: /mnt/Ironwolf-4TB/Models/OpenVINO/Qwen3.5/Qwen3.5-0.8B-int8_asym-ov/
device: CPU
runtime_config:
PERFORMANCE_HINT: LATENCY
samplers:
temperature: 0.7
top_k: 40
top_p: 0.95
repetition_penalty: 1.05
max_tokens: 1024


kokoro:
engine: openvino
model_type: kokoro
model_path:
device: CPU
kokoro_options:
voice: af_sarah
voice_blend: af_heart:0.7,af_nicole:0.3
lang_code:
speed: 1.0
chracter_count_chunk: 100

qwen3asr:
engine: openvino
model_type: qwen3_asr
model_path:
device: CPU
qwen3_asr_options:
language:
max_tokens:
max_chunk_sec:
search_expand_sec:
min_window_ms:


qwen3_tts_elmo:
model_type: qwen3_tts_voice_clone
model_path:
engine: openvino
device: GPU.0

24 changes: 24 additions & 0 deletions docs/configure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
runtime_config


runtime_config is an OpenArc entrypoint to the *properties* way of configuring openvino runtime. These settings allow users to tune the behavior of openivno runtime without needing to change application logic and are meant to be "portable", requring no code changes. Since OpenArc

OpenArc does not validate these, and OpenVINO upstream does not provide a way to check the behvaior of these settings in all cases. They can help you access hardware features not available to all devices like `SCHEDULING_CORE_TYPE` for more recent Intel CPUs, debug numeircal precision issues with `INFERENCE_PRECISION_HINT` or control `KV_CACHE_PRECISION`.

*properties* have the worst documentation in all of OpenVINO ecosystem, yet they are used everywhere in the openvino_notebooks, PRs and sometimes are even hardcoded depending on the needs of OpenVINO team. In that way, poking at these settings can drastically change performance but have less knobs than users of projects like `llama.cpp`, `vllm`, `sglang` are familiar with making.


Even though we can learn from the source code what these settings do knowing when they are useful comes with practice


ATTENTION_BACKEND "SDPA", "PA"
KV_CACHE_PRECISION "u4", "u8", "f16", "f32"
PERFORMANCE_HINT "LATNENCY", "THROUGHPUT"
EXECUTION_MODE_HINT "ACCURACY", "PERFORMANCE"
INFERENCE_PRECISION_HINT "f16", "f32"
MODEL_DISTRIBUTION_POLICY "TENSOR_PARALLEL", "PIPELINE_PARALLEL"
ACTIVATIONS_SCALING_FACTOR:
DYNAMIC_QUANTIZATION_GROUP_SIZE: integer
ENABLE_HYPER_THREADING: bool, defaults to true
SCHEDULING_CORE_TYPE: "ANY_CORE", "ECORE_ONLY", "PCORE_ONLY"
LOG_LEVEL: "ERR", "WARN", "INFO", "DEBUG", "TRACE" # might require building openvino
Binary file not shown.
4 changes: 2 additions & 2 deletions src/engine/openvino/kokoro.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@


from src.server.model_registry import ModelRegistry
from src.server.models.registration import ModelLoadConfig
from src.server.models.openvino import OV_KokoroGenConfig
from src.server.schemas.registration import ModelLoadConfig
from src.server.schemas.modeling.contract_kokoro import OV_KokoroGenConfig


class StreamChunk(NamedTuple):
Expand Down
4 changes: 2 additions & 2 deletions src/engine/openvino/qwen3_asr/qwen3_asr.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@
validate_language,
)

from src.server.models.openvino import OV_Qwen3ASRGenConfig
from src.server.schemas.modeling.contract_qwen3asr import OV_Qwen3ASRGenConfig
from src.server.model_registry import ModelRegistry
from src.server.models.registration import EngineType, ModelLoadConfig, ModelType
from src.server.schemas.registration import EngineType, ModelLoadConfig, ModelType

logger = logging.getLogger(__name__)

Expand Down
43 changes: 28 additions & 15 deletions src/engine/openvino/qwen3_tts/qwen3_tts.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,13 @@
_SYNTH_TMPL,
)
from src.server.model_registry import ModelRegistry
from src.server.models.openvino import OV_Qwen3TTSGenConfig
from src.server.models.registration import EngineType, ModelLoadConfig, ModelType
from src.server.schemas.modeling.contract_qwen3tts import (
OV_Qwen3TTSCustomVoice,
OV_Qwen3TTSVoiceClone,
OV_Qwen3TTSVoiceDesign,
OV_Qwen3TTSGenConfig,
)
from src.server.schemas.registration import EngineType, ModelLoadConfig, ModelType

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -198,27 +203,33 @@ def generate_stream(self, gen_config: OV_Qwen3TTSGenConfig) -> Iterator[TTSStrea
if not self._loaded:
raise RuntimeError("Call load_model() before generate_stream()")
gc = gen_config.model_copy(update={"non_streaming_mode": False})
if self.load_config.model_type == ModelType.QWEN3_TTS_VOICE_CLONE:
if isinstance(gc, OV_Qwen3TTSVoiceClone):
yield from self._generate_voice_clone_stream(gc)
else:
elif isinstance(gc, (OV_Qwen3TTSCustomVoice, OV_Qwen3TTSVoiceDesign)):
yield from self._generate_standard_stream(gc)
else:
raise TypeError(f"Unsupported gen_config type: {type(gc).__name__}")

def _generate_sync(self, gen_config: OV_Qwen3TTSGenConfig) -> tuple[np.ndarray, int]:
if not self._loaded:
raise RuntimeError("Call load_model() before generate()")
if self.load_config.model_type == ModelType.QWEN3_TTS_VOICE_CLONE:
if isinstance(gen_config, OV_Qwen3TTSVoiceClone):
return self._generate_voice_clone(gen_config)
return self._generate_standard(gen_config)
if isinstance(gen_config, (OV_Qwen3TTSCustomVoice, OV_Qwen3TTSVoiceDesign)):
return self._generate_standard(gen_config)
raise TypeError(f"Unsupported gen_config type: {type(gen_config).__name__}")

# ---- Internal: standard generation (custom_voice / voice_design) --------

def _generate_standard(self, gen_config: OV_Qwen3TTSGenConfig) -> tuple[np.ndarray, int]:
def _generate_standard(
self, gen_config: OV_Qwen3TTSCustomVoice | OV_Qwen3TTSVoiceDesign,
) -> tuple[np.ndarray, int]:
t_total = time.perf_counter()
perf: dict = {}
speaker = Speaker(gen_config.speaker) if gen_config.speaker else None
language = Language(gen_config.language) if gen_config.language else None

if self.load_config.model_type == ModelType.QWEN3_TTS_CUSTOM_VOICE:
if isinstance(gen_config, OV_Qwen3TTSCustomVoice):
speaker = Speaker(gen_config.speaker) if gen_config.speaker else None
build_kw = dict(
text=gen_config.input,
speaker=speaker,
Expand Down Expand Up @@ -251,7 +262,7 @@ def _generate_standard(self, gen_config: OV_Qwen3TTSGenConfig) -> tuple[np.ndarr

# ---- Internal: voice clone generation -----------------------------------

def _generate_voice_clone(self, gen_config: OV_Qwen3TTSGenConfig) -> tuple[np.ndarray, int]:
def _generate_voice_clone(self, gen_config: OV_Qwen3TTSVoiceClone) -> tuple[np.ndarray, int]:
t_total = time.perf_counter()
perf: dict = {}
language = Language(gen_config.language) if gen_config.language else None
Expand Down Expand Up @@ -303,13 +314,15 @@ def _generate_voice_clone(self, gen_config: OV_Qwen3TTSGenConfig) -> tuple[np.nd
self._log_pipeline_summary(perf, t_total, wav_seconds=float(len(wav) / SPEECH_DECODER_SR), voice_clone=True)
return wav, SPEECH_DECODER_SR

def _generate_standard_stream(self, gen_config: OV_Qwen3TTSGenConfig) -> Iterator[TTSStreamChunk]:
def _generate_standard_stream(
self, gen_config: OV_Qwen3TTSCustomVoice | OV_Qwen3TTSVoiceDesign,
) -> Iterator[TTSStreamChunk]:
t_total = time.perf_counter()
perf: dict = {}
speaker = Speaker(gen_config.speaker) if gen_config.speaker else None
language = Language(gen_config.language) if gen_config.language else None

if self.load_config.model_type == ModelType.QWEN3_TTS_CUSTOM_VOICE:
if isinstance(gen_config, OV_Qwen3TTSCustomVoice):
speaker = Speaker(gen_config.speaker) if gen_config.speaker else None
build_kw = dict(
text=gen_config.input,
speaker=speaker,
Expand Down Expand Up @@ -340,7 +353,7 @@ def _generate_standard_stream(self, gen_config: OV_Qwen3TTSGenConfig) -> Iterato
if n_samples > 0:
logger.info(f"[info] streaming: {n_chunks} chunks -> {n_samples} samples ({wav_sec:.2f}s audio)")

def _generate_voice_clone_stream(self, gen_config: OV_Qwen3TTSGenConfig) -> Iterator[TTSStreamChunk]:
def _generate_voice_clone_stream(self, gen_config: OV_Qwen3TTSVoiceClone) -> Iterator[TTSStreamChunk]:
t_total = time.perf_counter()
perf: dict = {}
language = Language(gen_config.language) if gen_config.language else None
Expand Down Expand Up @@ -1090,7 +1103,7 @@ def _log_summary(codes: list, wav: np.ndarray, t_total_start: float):
device=_device,
runtime_config={},
)
_gen = OV_Qwen3TTSGenConfig(
_gen = OV_Qwen3TTSVoiceClone(
input=_synth_text,
ref_audio_b64=_ref_b64,
ref_text=_ref_text,
Expand Down
4 changes: 2 additions & 2 deletions src/engine/optimum/optimum_emb.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
from transformers import AutoTokenizer
from optimum.intel import OVModelForFeatureExtraction

from src.server.models.optimum import PreTrainedTokenizerConfig
from src.server.schemas.modeling.contract_optimum_emb import PreTrainedTokenizerConfig

from typing import Any, AsyncIterator, Dict

from src.server.model_registry import ModelRegistry
from src.server.models.registration import ModelLoadConfig
from src.server.schemas.registration import ModelLoadConfig



Expand Down
Loading
Loading