# How to Implement Intent Analysis for Query Preprocessing in OpenViking

> Learn how to implement intent analysis for query preprocessing in OpenViking. Understand how OpenViking uses IntentAnalyzer to create structured QueryPlans for retrieval.

- Repository: [Volcengine/OpenViking](https://github.com/volcengine/OpenViking)
- Tags: how-to-guide
- Published: 2026-03-08

---

**OpenViking performs intent-driven hierarchical retrieval by analyzing user queries through the `IntentAnalyzer` class, which assembles session context, calls a VLM, and produces a structured `QueryPlan` to drive downstream retrieval.**

The **volcengine/OpenViking** repository implements a sophisticated retrieval system that preprocesses user queries through intent analysis before executing hierarchical searches. By understanding whether a user seeks memories, resources, or skills, the system optimizes retrieval paths through typed query decomposition. This article explains how to implement and customize this intent analysis pipeline using the actual source code from the OpenViking project.

## Understanding the IntentAnalyzer Architecture

The **`IntentAnalyzer`** class in [`openviking/retrieve/intent_analyzer.py`](https://github.com/volcengine/OpenViking/blob/main/openviking/retrieve/intent_analyzer.py) serves as the central component for query preprocessing. It transforms raw user input into a structured retrieval plan by coordinating context assembly, LLM interaction, and response parsing.

### Core Responsibilities

The analyzer executes a four-step pipeline:

1. **Context Collection** – Aggregates session compression summaries, recent message history, current user queries, optional `ContextType` constraints, and target directory abstracts.
2. **LLM Invocation** – Dispatches the assembled prompt to the configured vision language model via `vlm.get_completion_async`.
3. **Response Parsing** – Extracts JSON payloads using `parse_json_from_response` from [`openviking_cli/utils/llm.py`](https://github.com/volcengine/OpenViking/blob/main/openviking_cli/utils/llm.py), handling the `queries` list and `reasoning` fields.
4. **QueryPlan Generation** – Instantiates `TypedQuery` objects for each entry in the JSON array, wrapping them in a `QueryPlan` with session context and raw reasoning.

## Implementing Intent Analysis in Your Application

### Direct Usage of IntentAnalyzer

To implement intent analysis independently of the high-level file system API, instantiate the analyzer and provide session context:

```python
from openviking.retrieve.intent_analyzer import IntentAnalyzer
from openviking_cli.retrieve.types import ContextType

# Configure session data

compression_summary = "User is discussing project X architecture."
recent_messages = [
    {"role": "user", "content": "How do I store vectors?"},
    {"role": "assistant", "content": "You can use VikingDB..."},
]
current_query = "Show me examples of hierarchical retrieval."

# Optional constraints

target_context_type = ContextType.RESOURCE
target_abstract = "Resource folder for retrieval utilities."

# Initialize analyzer

analyzer = IntentAnalyzer(max_recent_messages=5)

# Generate query plan

query_plan = await analyzer.analyze(
    compression_summary=compression_summary,
    messages=recent_messages,
    current_message=current_query,
    context_type=target_context_type,
    target_abstract=target_abstract,
)

# Process typed queries

for typed_q in query_plan.queries:
    print(f"[{typed_q.context_type}] ({typed_q.priority}) {typed_q.query}")
    print(f"  Intent: {typed_q.intent}")

```

This implementation calls `_build_context_prompt` internally to assemble the prompt, then parses the LLM's JSON response into `TypedQuery` objects containing `query`, `context_type`, `intent`, `priority`, and optional `reasoning` fields.

### Integration with VikingFS.search

In production deployments, intent analysis triggers automatically within the high-level storage API. The `search` method in [`openviking/storage/viking_fs.py`](https://github.com/volcengine/OpenViking/blob/main/openviking/storage/viking_fs.py) (approximately lines 640-700) implements the following logic:

```python

# Inside VikingFS.search method

if session_summary or recent_messages:
    analyzer = IntentAnalyzer(max_recent_messages=5)
    query_plan = await analyzer.analyze(
        compression_summary=session_summary or "",
        messages=recent_messages or [],
        current_message=query,
        context_type=target_context_type,
        target_abstract=target_abstract,
    )
    typed_queries = query_plan.queries
    
    # Apply directory constraints if specified

    if target_uri:
        for tq in typed_queries:
            tq.target_directories = [target_uri]
else:
    # Fallback without intent analysis

    typed_queries = [
        TypedQuery(
            query=query,
            context_type=target_context_type,
            intent="",
            priority=3
        )
    ]

# typed_queries now drives HierarchicalRetriever

```

This integration demonstrates **session-aware preprocessing**: the analyzer only executes when session context exists, otherwise the system falls back to raw query processing.

## Customizing the Intent Analysis Prompt

The `IntentAnalyzer` delegates prompt construction to [`openviking/prompts.py`](https://github.com/volcengine/OpenViking/blob/main/openviking/prompts.py) using the template key `retrieval.intent_analysis`. The `_build_context_prompt` method (lines 20-27 in [`intent_analyzer.py`](https://github.com/volcengine/OpenViking/blob/main/intent_analyzer.py)) injects the following variables:

- **`compression_summary`** – Session overview or "None"
- **`recent_messages`** – Formatted message history (`[role]: content`)
- **`current_message`** – The active user query
- **`context_type`** – Optional constraint (`"memory"`, `"resource"`, or `"skill"`)
- **`target_abstract`** – Directory description for targeted searches

To customize behavior, modify the prompt template in [`openviking/prompts.py`](https://github.com/volcengine/OpenViking/blob/main/openviking/prompts.py) or override `_build_context_prompt` in a subclass. The LLM must return JSON matching the schema expected by `parse_json_from_response` in [`openviking_cli/utils/llm.py`](https://github.com/volcengine/OpenViking/blob/main/openviking_cli/utils/llm.py).

## Summary

- **IntentAnalyzer** in [`openviking/retrieve/intent_analyzer.py`](https://github.com/volcengine/OpenViking/blob/main/openviking/retrieve/intent_analyzer.py) provides the core preprocessing logic for OpenViking's retrieval system.
- The analyzer assembles session context, invokes the VLM via `vlm.get_completion_async`, and parses structured JSON into `TypedQuery` objects.
- **VikingFS.search** automatically triggers intent analysis when session summaries or recent messages are present, falling back to raw queries otherwise.
- The prompt template `retrieval.intent_analysis` controls LLM behavior and expects variables for compression summaries, message history, and target context types.

## Frequently Asked Questions

### How does OpenViking handle queries without session context?

When no `session_summary` or `recent_messages` are provided to `VikingFS.search`, the system bypasses `IntentAnalyzer` entirely. It creates a single `TypedQuery` object using the raw user query string, sets the priority to 3, and passes this directly to the `HierarchicalRetriever`.

### What is the difference between `TypedQuery` and `QueryPlan`?

A **`TypedQuery`** represents a single decomposed search intent with fields for `query` text, `context_type` (memory/resource/skill), `intent` description, `