Files
privateGPT/private_gpt/eager_loading.py
Javier Martinez cd8ca2214a feat: resumable chat worker + tool worker + async tokenizer (#2298)
* fix: avoid to block the loop

* fix: blocks in expansion

* fix: remove maximum concurrent users

...

* fix: multiplexer

* fix: readers

* fix: more fixes

...

* fix: impl

* feat: tool scheduler

* feat: add adaptative

* feat: add chat worker

* fix: max

* feat: add chat/tools workers

* fix: mypy

* feat: add generic scheduler

* fix: get result

* feat: do serializable the tool executor

* fix: tools

* fix: config

* fix: config

* fix: args

* fix: config

* fix: serializer

* Revert "fix: blocks in expansion"

This reverts commit a2110f94a8.

* fix: unify all logic

* feat: add ingestion scheduler

* fix: settings

* fix: config

* feat: add arq worker to chat

* fix: arq worker

* fix: add nest

* fix: mypy

* fix: await

* fix: script stress

* fix: tokenizer

* fix: chat scheduler

* fix: mypy

* fix: add async tokenizer

* fix: improve condense

* fix: tool scheduler

* feat: add initial real async chat worker

* fix: mypy

* fix: do resumable local executor

...

...

...

fix: revert usleess changes

fix: remove parent chat job

fix: refactor

fix: loop

ref: rename models

fix: chat engine

fix: mypy

...

...

...

fix: fix deps

* fix: tests

* fix: tests

* ...

* fix: stream

* fix: config

* fix: scheduler

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Handle PGPT_WORKER_MODE=celery in health check worker status

* fix: cancel

* fix: arch

* fix: test ingestion

* fix: deserialization of chat messages

* fix: broken results

* fix: mypy

* fix: test

* fix: config

* fix: remove arq tool worker

* fix: output cls

* fix: preserve early resumable tool callbacks

* fix: preserve async tool result order

* refactor: address worker PR review comments

* fix: mypy

* test: colocate ARQ chat enqueue coverage

* fix: remove redis from tests

* test: isolate chat mocks and cancellation timing

* fix: tests

(cherry picked from commit 218b599c66)

# Conflicts:
#	tests/server/chat/anthropic/test_anthropic_client.py
#	tests/server/chat/anthropic/test_langchain_anthropic.py
#	tests/server/chat/test_chat_knowledge_revamp.py
#	tests/server/chat/test_chat_routes.py
#	tests/server/chat/test_chat_routes_skills_integration.py

* fix: tests

(cherry picked from commit fc5ec0f72a)

* fix: ruff

* fix: test

* fix: worker config

(cherry picked from commit 1371c275a1)

* fix: principal

* test: remove flaky chat cancellation assertion

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-15 12:12:45 +02:00

103 lines
3.2 KiB
Python

"""Profile-based eager-loading of injector-bound components.
A single entry point ``warm(injector, profile)`` dispatches to the right
component groups based on the role. New worker types only need a new
profile entry — no changes anywhere else.
"""
import logging
from collections.abc import Callable, Sequence
from injector import Injector
from private_gpt.components.code_execution.code_execution_component import (
CodeExecutionComponent,
)
from private_gpt.components.embedding.embedding_component import EmbeddingComponent
from private_gpt.components.llm.llm_component import LLMComponent
from private_gpt.components.node_store.node_store_component import NodeStoreComponent
from private_gpt.components.prompts.prompt_builder import PromptBuilderService
from private_gpt.components.streaming.stream.stream_manager import StreamManager
from private_gpt.components.streaming.stream_component import StreamComponent
from private_gpt.components.vector_store.vector_store_component import (
VectorStoreComponent,
)
from private_gpt.server.tools.tool_service import ToolService
from private_gpt.settings.settings import Settings
logger = logging.getLogger(__name__)
_Warmer = Callable[[Injector], None]
def _warm_base(injector: Injector) -> None:
logger.debug("Warming base (settings + models)")
injector.get(Settings)
injector.get(LLMComponent)
injector.get(EmbeddingComponent)
def _warm_stores(injector: Injector) -> None:
logger.debug("Warming stores")
injector.get(NodeStoreComponent)
injector.get(VectorStoreComponent)
def _warm_streaming(injector: Injector) -> None:
logger.debug("Warming streaming components")
injector.get(StreamComponent)
injector.get(StreamManager)
def _warm_tools(injector: Injector) -> None:
logger.debug("Warming tools")
injector.get(PromptBuilderService)
injector.get(ToolService)
injector.get(CodeExecutionComponent)
def _warm_chat(injector: Injector) -> None:
from private_gpt.components.streaming.stream.stream_processor import (
StreamProcessor,
)
from private_gpt.server.chat.chat_service import ChatService
logger.debug("Warming chat-path components")
injector.get(ChatService)
injector.get(StreamProcessor)
_GROUPS: dict[str, _Warmer] = {
"base": _warm_base,
"stores": _warm_stores,
"streaming": _warm_streaming,
"tools": _warm_tools,
"chat": _warm_chat,
}
_PROFILES: dict[str, Sequence[str]] = {
"chat": ("base", "stores", "streaming", "tools", "chat"),
"tools": ("base", "tools"),
"full": ("base", "stores", "streaming", "tools"),
}
def warm(injector: Injector, profile: str = "full") -> None:
"""Eager-resolve all DI singletons for the given worker profile.
``profile`` is one of ``chat``, ``tools``, or ``full`` (API server).
"""
groups = _PROFILES.get(profile)
if groups is None:
raise ValueError(
f"Unknown warm-up profile {profile!r}. "
f"Available: {', '.join(sorted(_PROFILES))}"
)
logger.info("Warming profile=%s (groups: %s)", profile, ", ".join(groups))
for group in groups:
_GROUPS[group](injector)
def eager_loading(injector: Injector) -> None:
"""Full warm-up: everything. Kept for API server backward compat."""
warm(injector, "full")