Skip to content

Support conversational follow-up queries #18

Description

@SaitejaKommi

Priority

P1

Area

Query Engine / Session State

Problem

The search API is stateless. Users cannot refine searches conversationally (e.g. 'Show me high protein snacks' -> 'Which ones have the least sugar?' -> 'Only vegan ones'). The second turn currently evaluates as a brand new query, losing the 'high protein snacks' context.

Why This Matters

Real users search conversationally and incrementally. Losing context between turns frustrates users and forces them to retype long, complex queries. Maintaining cumulative constraint state makes AskOFF feel responsive and intelligent while preserving deterministic retrieval.

Current Behaviour

  • backend/query/pipeline.py processes each query string independently from scratch.
  • backend/query/constraint_extractor.py extracts filters afresh without prior context.
  • No session or query state merger exists in backend/.

Expected Behaviour

  • Conversation context is represented explicitly in API payloads or session state.
  • Follow-up constraints are combined correctly without silently losing prior constraints.
  • Core subject noun ('snacks') is retained unless explicitly replaced.
  • Ambiguous references are handled safely.
  • Search retrieval remains 100% deterministic OpenSearch queries.
  • Tests cover multi-turn query sequences.

Proposed Implementation

  1. Deterministic Constraint Merger: Implement refine(previous_query: SearchQuery, follow_up_text: str) -> SearchQuery in backend/query/pipeline.py:
    • Retain core subject unless follow-up introduces a new subject.
    • Merge boolean filters (e.g. high_protein: True + vegan: True).
    • Combine numeric bounds without overwrite unless explicitly updated.
    • Update ranking preferences (e.g. adding sort_nutrient: sugars, order: asc).
  2. State Payload in API: Support receiving active constraints in POST /search/refine or POST /bot/chat.
  3. Inspectable State: Expose cumulative merged state in SearchQuery.metadata.

Acceptance Criteria

  • Turn 1 (high protein snacks) + Turn 2 (lowest sugar) queries snacks with high protein sorted by sugar ascending.
  • Turn 3 (only vegan) adds vegan flag without losing previous constraints.
  • Explicit category changes cleanly reset the subject term.
  • Ambiguous references fail safely without silent weakening of constraints.
  • Existing behaviour is not regressed.
  • Appropriate regression tests are added.
  • Documentation is updated where necessary.

Implementation Prompt

First inspect the existing implementation and tests before making changes. Understand the current behaviour and identify the smallest appropriate change. Implement the requested functionality without unrelated refactoring. Add or update regression tests. Run the relevant tests, linting/type checks, and verification commands. Do not modify unrelated components.

Inspect `backend/query/pipeline.py`, `backend/query/search_query.py`, and `backend/query/constraint_extractor.py`.
Implement conversational query constraint merging:
1. In `backend/query/pipeline.py`, add a method `refine(previous_query: SearchQuery, follow_up_text: str) -> SearchQuery`.
2. Process the follow_up_text through normalizers and ConstraintExtractor.
3. Intelligently merge constraints: preserve existing boolean flags, combine numeric bounds, update ranking preferences, and retain the core subject noun unless explicitly replaced.
4. Expose the merged state in SearchQuery.metadata so the client can inspect applied cumulative filters.
5. Add unit tests in `backend/tests/test_conversational_query.py` demonstrating 3-turn refinement scenarios.

Verification Plan

Run conversational query tests:

pytest backend/tests/test_conversational_query.py -v
pytest backend/tests/test_query_engine.py -v

Dependencies

Backlog IDs 2 and 15

Maintainer Decision Required

No maintainer decision required.

Out of Scope

  • Storing user chat histories indefinitely in a database.
  • Using an LLM to rewrite search queries.

Relevant Files

  • backend/query/pipeline.py
  • backend/query/search_query.py
  • backend/query/constraint_extractor.py
  • backend/api/routes.py
  • backend/tests/test_conversational_query.py

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High priority issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions