Source code for langchain_community.tools.json.tool
# flake8: noqa
"""用于处理JSON规范的工具。"""
from __future__ import annotations
import json
import re
from pathlib import Path
from typing import Dict, List, Optional, Union
from langchain_core.pydantic_v1 import BaseModel
from langchain_core.callbacks import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain_core.tools import BaseTool
def _parse_input(text: str) -> List[Union[str, int]]:
"""将形式为data["key1"][0]["key2"]的输入解析为键列表。"""
_res = re.findall(r"\[.*?]", text)
# strip the brackets and quotes, convert to int if possible
res = [i[1:-1].replace('"', "").replace("'", "") for i in _res]
res = [int(i) if i.isdigit() else i for i in res]
return res
[docs]class JsonSpec(BaseModel):
"""JSON规范的基类。"""
dict_: Dict
max_value_length: int = 200
[docs] @classmethod
def from_file(cls, path: Path) -> JsonSpec:
"""从文件中创建一个JsonSpec。"""
if not path.exists():
raise FileNotFoundError(f"File not found: {path}")
dict_ = json.loads(path.read_text())
return cls(dict_=dict_)
[docs] def keys(self, text: str) -> str:
"""返回给定路径上字典的键。
参数:
text:字典路径的Python表示(例如 data["key1"][0]["key2"])。
"""
try:
items = _parse_input(text)
val = self.dict_
for i in items:
if i:
val = val[i]
if not isinstance(val, dict):
raise ValueError(
f"Value at path `{text}` is not a dict, get the value directly."
)
return str(list(val.keys()))
except Exception as e:
return repr(e)
[docs] def value(self, text: str) -> str:
"""返回给定路径的字典的值。
参数:
text:字典路径的Python表示(例如 data["key1"][0]["key2"])。
"""
try:
items = _parse_input(text)
val = self.dict_
for i in items:
val = val[i]
if isinstance(val, dict) and len(str(val)) > self.max_value_length:
return "Value is a large dictionary, should explore its keys directly"
str_val = str(val)
if len(str_val) > self.max_value_length:
str_val = str_val[: self.max_value_length] + "..."
return str_val
except Exception as e:
return repr(e)
[docs]class JsonListKeysTool(BaseTool):
"""用于列出JSON规范中键的工具。"""
name: str = "json_spec_list_keys"
description: str = """
Can be used to list all keys at a given path.
Before calling this you should be SURE that the path to this exists.
The input is a text representation of the path to the dict in Python syntax (e.g. data["key1"][0]["key2"]).
"""
spec: JsonSpec
def _run(
self,
tool_input: str,
run_manager: Optional[CallbackManagerForToolRun] = None,
) -> str:
return self.spec.keys(tool_input)
async def _arun(
self,
tool_input: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
return self._run(tool_input)
[docs]class JsonGetValueTool(BaseTool):
"""用于从JSON规范中获取值的工具。"""
name: str = "json_spec_get_value"
description: str = """
Can be used to see value in string format at a given path.
Before calling this you should be SURE that the path to this exists.
The input is a text representation of the path to the dict in Python syntax (e.g. data["key1"][0]["key2"]).
"""
spec: JsonSpec
def _run(
self,
tool_input: str,
run_manager: Optional[CallbackManagerForToolRun] = None,
) -> str:
return self.spec.value(tool_input)
async def _arun(
self,
tool_input: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
return self._run(tool_input)