73 lines
2.4 KiB
Python
73 lines
2.4 KiB
Python
"""LlamaIndex Tool classes."""
|
|
|
|
from typing import Any, Dict, List
|
|
|
|
from llama_index.bridge.langchain import BaseTool
|
|
from llama_index.bridge.pydantic import BaseModel, Field
|
|
from llama_index.core.base_query_engine import BaseQueryEngine
|
|
from llama_index.core.response.schema import RESPONSE_TYPE
|
|
from llama_index.schema import TextNode
|
|
|
|
|
|
def _get_response_with_sources(response: RESPONSE_TYPE) -> str:
|
|
"""Return a response with source node info."""
|
|
source_data: List[Dict[str, Any]] = []
|
|
for source_node in response.source_nodes:
|
|
metadata = {}
|
|
if isinstance(source_node.node, TextNode):
|
|
start = source_node.node.start_char_idx
|
|
end = source_node.node.end_char_idx
|
|
if start is not None and end is not None:
|
|
metadata.update({"start_char_idx": start, "end_char_idx": end})
|
|
|
|
source_data.append(metadata)
|
|
source_data[-1]["ref_doc_id"] = source_node.node.ref_doc_id
|
|
source_data[-1]["score"] = source_node.score
|
|
return str({"answer": str(response), "sources": source_data})
|
|
|
|
|
|
class IndexToolConfig(BaseModel):
|
|
"""Configuration for LlamaIndex index tool."""
|
|
|
|
query_engine: BaseQueryEngine
|
|
name: str
|
|
description: str
|
|
tool_kwargs: Dict = Field(default_factory=dict)
|
|
|
|
class Config:
|
|
"""Configuration for this pydantic object."""
|
|
|
|
arbitrary_types_allowed = True
|
|
|
|
|
|
class LlamaIndexTool(BaseTool):
|
|
"""Tool for querying a LlamaIndex."""
|
|
|
|
# NOTE: name/description still needs to be set
|
|
query_engine: BaseQueryEngine
|
|
return_sources: bool = False
|
|
|
|
@classmethod
|
|
def from_tool_config(cls, tool_config: IndexToolConfig) -> "LlamaIndexTool":
|
|
"""Create a tool from a tool config."""
|
|
return_sources = tool_config.tool_kwargs.pop("return_sources", False)
|
|
return cls(
|
|
query_engine=tool_config.query_engine,
|
|
name=tool_config.name,
|
|
description=tool_config.description,
|
|
return_sources=return_sources,
|
|
**tool_config.tool_kwargs,
|
|
)
|
|
|
|
def _run(self, input: str) -> str:
|
|
response = self.query_engine.query(input)
|
|
if self.return_sources:
|
|
return _get_response_with_sources(response)
|
|
return str(response)
|
|
|
|
async def _arun(self, input: str) -> str:
|
|
response = await self.query_engine.aquery(input)
|
|
if self.return_sources:
|
|
return _get_response_with_sources(response)
|
|
return str(response)
|