llama-index
72 строки · 2.5 Кб
1"""LlamaIndex Tool classes."""
2
3from typing import Any, Dict, List4
5from llama_index.legacy.bridge.langchain import BaseTool6from llama_index.legacy.bridge.pydantic import BaseModel, Field7from llama_index.legacy.core.base_query_engine import BaseQueryEngine8from llama_index.legacy.core.response.schema import RESPONSE_TYPE9from llama_index.legacy.schema import TextNode10
11
12def _get_response_with_sources(response: RESPONSE_TYPE) -> str:13"""Return a response with source node info."""14source_data: List[Dict[str, Any]] = []15for source_node in response.source_nodes:16metadata = {}17if isinstance(source_node.node, TextNode):18start = source_node.node.start_char_idx19end = source_node.node.end_char_idx20if start is not None and end is not None:21metadata.update({"start_char_idx": start, "end_char_idx": end})22
23source_data.append(metadata)24source_data[-1]["ref_doc_id"] = source_node.node.ref_doc_id25source_data[-1]["score"] = source_node.score26return str({"answer": str(response), "sources": source_data})27
28
29class IndexToolConfig(BaseModel):30"""Configuration for LlamaIndex index tool."""31
32query_engine: BaseQueryEngine33name: str34description: str35tool_kwargs: Dict = Field(default_factory=dict)36
37class Config:38"""Configuration for this pydantic object."""39
40arbitrary_types_allowed = True41
42
43class LlamaIndexTool(BaseTool):44"""Tool for querying a LlamaIndex."""45
46# NOTE: name/description still needs to be set47query_engine: BaseQueryEngine48return_sources: bool = False49
50@classmethod51def from_tool_config(cls, tool_config: IndexToolConfig) -> "LlamaIndexTool":52"""Create a tool from a tool config."""53return_sources = tool_config.tool_kwargs.pop("return_sources", False)54return cls(55query_engine=tool_config.query_engine,56name=tool_config.name,57description=tool_config.description,58return_sources=return_sources,59**tool_config.tool_kwargs,60)61
62def _run(self, input: str) -> str:63response = self.query_engine.query(input)64if self.return_sources:65return _get_response_with_sources(response)66return str(response)67
68async def _arun(self, input: str) -> str:69response = await self.query_engine.aquery(input)70if self.return_sources:71return _get_response_with_sources(response)72return str(response)73