e4dcfc49aa
Tests / Import Check (Python 3.13) (push) Has been cancelled
Tests / Import Check (Python 3.14) (push) Has been cancelled
Tests / Python Tests (Python 3.11) (push) Has been cancelled
Tests / Python Tests (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.14) (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled
Tests / Lint and Format (push) Has been cancelled
Tests / Web Node Tests (push) Has been cancelled
Tests / Import Check (Python 3.11) (push) Has been cancelled
Tests / Import Check (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.13) (push) Has been cancelled
111 lines
3.3 KiB
Python
111 lines
3.3 KiB
Python
"""RAG query tool — thin wrapper around :class:`RAGService`.
|
|
|
|
The chat pipeline always passes an explicit ``kb_name`` selected by the user;
|
|
this module therefore never resolves aliases or falls back to a default KB.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from typing import Dict, List, Optional
|
|
|
|
from deeptutor.services.rag.service import RAGService
|
|
|
|
|
|
async def rag_search(
|
|
query: str,
|
|
kb_name: str,
|
|
provider: Optional[str] = None,
|
|
kb_base_dir: Optional[str] = None,
|
|
event_sink=None,
|
|
**kwargs,
|
|
) -> dict:
|
|
"""Retrieve passages from ``kb_name`` and synthesise an answer.
|
|
|
|
``kb_name`` must match a knowledge base the current user can access;
|
|
multi-user routing is delegated to :func:`resolve_for_rag` when no
|
|
explicit ``kb_base_dir`` is given.
|
|
"""
|
|
query = query.strip() if isinstance(query, str) else ""
|
|
kb_name = kb_name.strip() if isinstance(kb_name, str) else ""
|
|
if not query:
|
|
raise ValueError("RAG query must be a non-empty string.")
|
|
if not kb_name:
|
|
raise ValueError("RAG requires an explicit kb_name.")
|
|
|
|
if kb_base_dir is None:
|
|
from deeptutor.multi_user.knowledge_access import resolve_for_rag
|
|
|
|
resource = resolve_for_rag(kb_name)
|
|
if resource is None:
|
|
raise ValueError(f"Knowledge base '{kb_name}' is not accessible.")
|
|
kb_base_dir = str(resource.base_dir)
|
|
kb_name = resource.name
|
|
|
|
service = RAGService(kb_base_dir=kb_base_dir, provider=provider)
|
|
return await service.search(
|
|
query=query,
|
|
kb_name=kb_name,
|
|
event_sink=event_sink,
|
|
**kwargs,
|
|
)
|
|
|
|
|
|
async def initialize_rag(
|
|
kb_name: str,
|
|
documents: List[str],
|
|
provider: Optional[str] = None,
|
|
kb_base_dir: Optional[str] = None,
|
|
**kwargs,
|
|
) -> bool:
|
|
"""Index ``documents`` into ``kb_name`` using the configured RAG pipeline."""
|
|
service = RAGService(kb_base_dir=kb_base_dir, provider=provider)
|
|
return await service.initialize(kb_name=kb_name, file_paths=documents, **kwargs)
|
|
|
|
|
|
async def delete_rag(
|
|
kb_name: str,
|
|
provider: Optional[str] = None,
|
|
kb_base_dir: Optional[str] = None,
|
|
) -> bool:
|
|
"""Delete the knowledge base ``kb_name``."""
|
|
service = RAGService(kb_base_dir=kb_base_dir, provider=provider)
|
|
return await service.delete(kb_name=kb_name)
|
|
|
|
|
|
def get_available_providers() -> List[Dict]:
|
|
return RAGService.list_providers()
|
|
|
|
|
|
def get_current_provider() -> str:
|
|
return RAGService.get_current_provider()
|
|
|
|
|
|
# Backward-compat aliases used by a few callers / tests
|
|
get_available_plugins = get_available_providers
|
|
list_providers = RAGService.list_providers
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
|
|
if sys.platform == "win32":
|
|
import io
|
|
|
|
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
|
|
|
|
print("Available RAG Pipelines:")
|
|
for provider in get_available_providers():
|
|
print(f" - {provider['id']}: {provider['description']}")
|
|
print(f"\nCurrent provider: {get_current_provider()}\n")
|
|
|
|
result = asyncio.run(
|
|
rag_search(
|
|
"What is the lookup table (LUT) in FPGA?",
|
|
kb_name="DE-all",
|
|
)
|
|
)
|
|
print(f"Query: {result['query']}")
|
|
print(f"Answer: {result['answer']}")
|
|
print(f"Provider: {result.get('provider', 'unknown')}")
|