fix: improve perf (#2322)

* fix: improve perf

* Revert "fix: improve perf"

This reverts commit f558dd431c.

* Revert "fix: avoid duplicating deltas (#2321)"

This reverts commit b6be07c2ae.
This commit is contained in:
Javier Martinez
2026-07-30 15:15:41 +02:00
committed by GitHub
parent 94710b9272
commit e534667c98
3 changed files with 2 additions and 121 deletions

View File

@@ -19,9 +19,6 @@ from private_gpt.server.chat.interceptors.configure_tool_execution_interceptor i
from private_gpt.server.chat.interceptors.configure_tool_interceptor import (
ConfigureToolRequestInterceptor,
)
from private_gpt.server.chat.interceptors.deduplicate_event_interceptor import (
DeduplicateEventInterceptor,
)
from private_gpt.server.chat.interceptors.default_values_interceptor import (
DefaultValuesRequestInterceptor,
)
@@ -108,7 +105,6 @@ class ChatInterceptorService:
# --- response interceptors (run each iteration, order matters) ---
extract_citation_response_interceptor: ExtractCitationInterceptor,
filter_event_by_type_interceptor: FilterZylonInterceptor,
deduplicate_event_interceptor: DeduplicateEventInterceptor,
) -> None:
self._prompt_builder_service = prompt_builder_service
@@ -202,7 +198,6 @@ class ChatInterceptorService:
"sanity",
responses=[
filter_event_by_type_interceptor,
deduplicate_event_interceptor,
],
)
)

View File

@@ -1,49 +0,0 @@
from collections.abc import Mapping
from typing import Any
from private_gpt.components.engines.chat.interceptors.chat_interceptor import (
ChatResponseLoopInterceptor,
)
from private_gpt.components.engines.chat.models.chat_interceptor_context import (
ChatInterceptorContext,
)
from private_gpt.events.models import Event, PingEvent
class DeduplicateEventInterceptor(ChatResponseLoopInterceptor):
"""Drop consecutive duplicate streamed events (except pings).
Some providers re-emit identical ``content_block_delta`` payloads (e.g.
``input_json_delta`` with an unchanged ``partial_json_obj``). Those
duplicates add noise for clients without changing state, so they are
suppressed. Ping keepalives are always forwarded.
"""
def __init__(self) -> None:
self._last_fingerprint: str | None = None
async def on_iteration_start(self, context: ChatInterceptorContext) -> None:
self._last_fingerprint = None
async def on_iteration_end(self, context: ChatInterceptorContext) -> None:
self._last_fingerprint = None
async def intercept_event(
self,
event: Event,
context: ChatInterceptorContext,
) -> Event | None:
if isinstance(event, PingEvent):
return event
fingerprint = event.model_dump_json()
if fingerprint == self._last_fingerprint:
return None
self._last_fingerprint = fingerprint
return event
def model_copy(
self, *, update: Mapping[str, Any] | None | None = None, deep: bool = False
) -> "DeduplicateEventInterceptor":
return DeduplicateEventInterceptor()

View File

@@ -55,9 +55,6 @@ from private_gpt.events.models import (
ToolUseBlock,
Usage,
)
from private_gpt.server.chat.interceptors.deduplicate_event_interceptor import (
DeduplicateEventInterceptor,
)
from private_gpt.server.chat.interceptors.filter_event_by_type_interceptor import (
FilterZylonInterceptor,
)
@@ -84,10 +81,7 @@ async def _collect_from_gen(
ping_interval: float | None = None,
) -> list:
"""Pipe a hand-crafted event generator through the interceptor pipeline."""
interceptors: list[ChatResponseLoopInterceptor] = [
FilterZylonInterceptor(),
DeduplicateEventInterceptor(),
]
interceptors: list[ChatResponseLoopInterceptor] = [FilterZylonInterceptor()]
if ping_interval:
gen = await PingEventInterceptor(ping_interval).intercept(gen)
@@ -146,10 +140,7 @@ def _make_engine(
) -> ChatLoopEngine:
llm_component = MagicMock(spec=LLMComponent)
llm_component.get_llm.return_value = mock_llm
interceptors: list[ChatResponseLoopInterceptor] = [
FilterZylonInterceptor(),
DeduplicateEventInterceptor(),
]
interceptors: list[ChatResponseLoopInterceptor] = [FilterZylonInterceptor()]
return ChatLoopEngine(
llm_component=llm_component,
response_interceptors=interceptors,
@@ -639,62 +630,6 @@ async def test_integration_ping_injected_between_slow_llm_chunks() -> None:
assert sum(1 for e in events if isinstance(e, PingEvent)) >= 1
@pytest.mark.asyncio
async def test_unit_duplicate_content_block_deltas_are_dropped() -> None:
"""Identical consecutive content_block_delta events are suppressed."""
from private_gpt.events.models import InputJSONDelta
bid = _block_id()
delta = InputJSONDelta(
partial_json="",
partial_json_obj={"object": "deals", "query": None},
)
async def gen() -> AsyncGenerator:
yield RawMessageStartEvent.from_defaults()
yield RawContentBlockStartEvent(
index=1,
block_id=bid,
content_block=ToolUseBlock(id="tool_1", name="search", input={}),
)
for _ in range(5):
yield RawContentBlockDeltaEvent(
index=1,
block_id=bid,
delta=delta.model_copy(deep=True),
)
yield RawContentBlockDeltaEvent(
index=1,
block_id=bid,
delta=InputJSONDelta(
partial_json='{"object":"deals","query":"x"}',
partial_json_obj={"object": "deals", "query": "x"},
),
)
yield RawContentBlockStopEvent(index=1, block_id=bid)
yield RawMessageStopEvent()
events = await _collect_from_gen(gen())
deltas = [e for e in events if isinstance(e, RawContentBlockDeltaEvent)]
assert len(deltas) == 2
assert deltas[0].delta.partial_json_obj == {"object": "deals", "query": None}
assert deltas[1].delta.partial_json_obj == {"object": "deals", "query": "x"}
@pytest.mark.asyncio
async def test_unit_ping_events_are_never_deduplicated() -> None:
"""Ping keepalives always pass through even when consecutive."""
async def gen() -> AsyncGenerator:
yield PingEvent()
yield PingEvent()
yield PingEvent()
events = await _collect_from_gen(gen())
assert len(events) == 3
assert all(isinstance(e, PingEvent) for e in events)
# ---------------------------------------------------------------------------
# Private factory helpers
# ---------------------------------------------------------------------------