63 lines
3.2 KiB
Markdown
63 lines
3.2 KiB
Markdown
## Context
|
|
|
|
`LookupKnowledgeTool` currently performs L0 keyword matching first. If L0 returns exactly one document, the tool treats it as high confidence, skips L1 semantic retrieval, and returns the L0-derived primary result. This was useful for the MVP but conflicts with the RAG refactor direction: L0 should constrain and explain retrieval, not decide final evidence by itself.
|
|
|
|
The refactor plan keeps L0 and metadata as valuable business signals. This change narrows L0 to a domain/entity hint provider while keeping `lookup_knowledge` as the explicit Agent tool entry point and preserving `tool_invocation` observability.
|
|
|
|
## Goals / Non-Goals
|
|
|
|
**Goals:**
|
|
|
|
- Produce structured L0 hints from current keyword/frontmatter matches.
|
|
- Include matched keywords, domains, entities, and titles in the trace.
|
|
- Run L1 retrieval by default even for unique L0 hits.
|
|
- Use a single clear L0 domain as a category filter for L1.
|
|
- Preserve existing result shape as much as possible.
|
|
|
|
**Non-Goals:**
|
|
|
|
- Do not migrate to Spring AI VectorStore.
|
|
- Do not implement BM25, RRF, rerank, or evidence packing.
|
|
- Do not change document upload, chunking, or Milvus schema.
|
|
- Do not remove L0.
|
|
|
|
## Decisions
|
|
|
|
### Decision: Add a structured L0 hint result beside existing exact matches
|
|
|
|
`KnowledgeIndexService` will expose an `analyzeQuery` style method that returns:
|
|
|
|
- matched entries
|
|
- matched keywords
|
|
- domains/categories
|
|
- entity terms
|
|
|
|
The existing `exactMatch` method can remain for compatibility.
|
|
|
|
Rationale: this avoids rewriting all callers while giving `LookupKnowledgeTool` richer data for tracing and filtering.
|
|
|
|
### Decision: Treat L0 unique hit as a hint, not a short circuit
|
|
|
|
`LookupKnowledgeTool` will no longer skip L1 solely because L0 matched one document. L1 will be called using the query and an optional category filter when L0 provides exactly one clear domain.
|
|
|
|
Rationale: the upcoming Spring AI retriever and evidence post-processing pipeline needs L0 and L1 to cooperate rather than use early return semantics.
|
|
|
|
### Decision: Keep `PRECISE` only when L0 and L1 both support the result
|
|
|
|
The relevance assessment should not mark `PRECISE` just because L0 matched once. It may mark `PRECISE` when L0 has one match and L1 returns evidence above the configured high relevance threshold, or when L0 has one match and L1 cannot run but the L0 result is still available.
|
|
|
|
Rationale: this preserves a graceful fallback while reducing overconfidence when semantic evidence disagrees.
|
|
|
|
### Decision: Persist L0 hints in retrieval details
|
|
|
|
`ToolInvocationRecorder.LookupKnowledgeRecord` will include fields for L0 matched keywords, domains, and entities. These will be serialized into `retrieval_details`.
|
|
|
|
Rationale: evidence trace and later evaluation need to explain why metadata filters or query augmentation happened.
|
|
|
|
## Risks / Trade-offs
|
|
|
|
- Increased latency because L1 is called more often -> keep topK small and allow category filter to reduce search scope.
|
|
- L0 domain filter may be too narrow -> only apply it when there is exactly one nonblank domain; otherwise search without filter.
|
|
- Existing tests may assume `L0` retrieval layer for unique hits -> update expectations to `L0+L1` when L1 participates.
|
|
- If L1 fails, the tool should still return L0 evidence rather than fail the entire knowledge lookup.
|