Skip to content

feat(conversational): session-aware conversational search (Sprint 3)#3

Merged
svalench merged 2 commits into
feat/langgraph-search-pipelinefrom
feat/conversational-search
May 8, 2026
Merged

feat(conversational): session-aware conversational search (Sprint 3)#3
svalench merged 2 commits into
feat/langgraph-search-pipelinefrom
feat/conversational-search

Conversation

@svalench
Copy link
Copy Markdown
Owner

@svalench svalench commented May 8, 2026

Summary

Sprint 3 of the LangGraph roadmap: an optional conversational search layer on top of the existing Searcher. Stacked on top of #2 (Sprint 1+2).

The new endpoint is search-first, not chat-first — it remembers a tiny per-session history, rewrites short follow-ups using the previous turn, and returns a structured clarification_needed flag for ambiguous input rather than hallucinating a query.

What's new

Settings: CONVERSATIONAL section

GRAPH_SEARCH = {
    "CONVERSATIONAL": {
        "ENABLED": False,
        "MEMORY_BACKEND": "inmemory",   # alias or dotted path
        "MEMORY_OPTIONS": {},
        "MAX_HISTORY_ITEMS": 10,
        "ALLOW_CLARIFICATIONS": True,
        "MIN_QUERY_LENGTH_FOR_AUTOSEARCH": 2,
    },
}

Memory backends (memory/ subpackage)

  • BaseMemoryBackend + ConversationEvent dataclass.
  • InMemoryBackend — thread-safe bounded deque, default for tests/dev.
  • DjangoCacheBackend — works with any Django cache (incl. Redis via django-redis) without a hard Redis dependency.
  • build_memory_backend factory with short aliases (inmemory, cache, redis).

Top results are stored in compact form (model + pk + score only), so backends stay serialisation-friendly.

Conversation graph (langgraph_conversation.py)

load_context → interpret_followup → maybe_clarify → [execute_search] → store_context
  • interpret_followup resolves more / similar / only X patterns deterministically — never invents filters.
  • maybe_clarify returns clarification_needed=True for ambiguous short input without history.
  • Same fallback runner as the search graph, so it works without the langgraph package.

New endpoint

POST /api/search/conversation/
DELETE /api/search/conversation/?conversation_id=...

Returns 404 when CONVERSATIONAL.ENABLED = False so the URL is safe to leave registered globally.

Sample request/response:

// Request
{"query": "only products", "conversation_id": "abc-123", "models": ["shop.Product"], "limit": 5}

// Response
{
  "conversation_id": "abc-123",
  "query": "only products",
  "interpreted_query": "red phone",
  "clarification_needed": false,
  "clarification_message": "",
  "results": [...],
  "total": 5
}

Tests

tests/test_conversational_search.py — 16 new tests covering:

  • Memory backends (truncation, clear, factory aliases, event round-trip).
  • Each node in isolation (followup rewriting, only-X filter, clarification trigger).
  • Graph end-to-end: search execution + history persistence, follow-up uses previous context, ambiguous input returns clarification.
  • View: 404 when disabled, full pipeline, follow-up across two HTTP calls, clear history.
36 passed in 0.27s   # 8 original + 13 from PR #2 + 15 from this PR

Backwards compatibility

  • Existing /api/search/ and /api/search/similar/ endpoints untouched.
  • All pre-existing tests still pass.
  • Endpoint is opt-in: returns 404 by default.

What's next (Sprint 4 — separate PR)

Smart structured indexing pipeline, optional streaming/event hook system, and production hardening (limits, structured logging, traces).

svalench added 2 commits May 8, 2026 07:04
Adds Sprint 3: an optional conversational search layer on top of the
existing Searcher / LangGraph pipeline.

Highlights:
* New CONVERSATIONAL settings section with safe defaults (disabled).
* New memory/ subpackage:
  - BaseMemoryBackend contract + ConversationEvent dataclass.
  - InMemoryBackend (process-local, thread-safe, bounded deque).
  - DjangoCacheBackend (works with any Django cache, including Redis
    via django-redis, without taking a hard Redis dependency).
  - build_memory_backend factory with short aliases (inmemory, cache,
    redis) and dotted-path support.
* New langgraph_conversation module with the conversational graph:
  load_context -> interpret_followup -> maybe_clarify ->
  [execute_search] -> store_context, plus an in-tree fallback runner.
* Follow-up interpretation is conservative on purpose: 'more',
  'similar', 'only X' patterns reuse the previous turn; otherwise the
  query is left untouched. Ambiguous short follow-ups produce a
  structured clarification_needed flag rather than a hallucinated
  query.
* Top results are persisted to memory in a compact form (model + pk +
  score only) so backends remain serialisation-friendly.
* New ConversationalSearchAPIView mounted at
  POST /api/search/conversation/ (and DELETE for clearing history).
  Returns 404 when CONVERSATIONAL.ENABLED is False so the URL is safe
  to leave registered globally.
* 16 new tests cover memory backends, individual nodes, end-to-end
  graph behaviour and the HTTP view.

Backwards compatibility:
* All previous tests still pass unchanged (36 passed total).
* Existing /api/search/ and /api/search/similar/ endpoints are
  untouched.
@svalench svalench merged commit d3009a8 into feat/langgraph-search-pipeline May 8, 2026
0 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant