byArMan456 commited on
Commit
75d90d5
·
verified ·
1 Parent(s): 314150e

Create tools

Browse files
Files changed (1) hide show
  1. tools +185 -0
tools ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ """Comprehensive, **key‑free** toolset for the LangGraph agent.
4
+ Every tool is fully self‑contained and safe to run inside a public
5
+ Hugging Face Space – no private API keys required.
6
+ Capabilities covered (GAIA L1):
7
+ • general web search • Wikipedia summary • light image inspection
8
+ • basic math • current time • YouTube video metadata
9
+ • inspect Excel files
10
+ """
11
+
12
+ import datetime
13
+ import io
14
+ import math
15
+ import pathlib
16
+ import re
17
+ import statistics
18
+ from typing import List, Dict, Any
19
+
20
+ import pandas as pd
21
+ import requests
22
+ from bs4 import BeautifulSoup
23
+ from langchain.tools import tool, BaseTool
24
+ from PIL import Image
25
+ from pytube import YouTube
26
+
27
+
28
+ # ---------------------------------------------------------------------------
29
+ # Helper utilities -----------------------------------------------------------
30
+ # ---------------------------------------------------------------------------
31
+
32
+ def _html_text(soup: BeautifulSoup) -> str:
33
+ return re.sub(r"\s+", " ", soup.get_text(" ").strip())
34
+
35
+
36
+ # ---------------------------------------------------------------------------
37
+ # Time & math ----------------------------------------------------------------
38
+ # ---------------------------------------------------------------------------
39
+
40
+ @tool
41
+ def get_current_time() -> str:
42
+ """Return the current UTC time (ISO‑8601)."""
43
+ return datetime.datetime.utcnow().isoformat()
44
+
45
+
46
+ @tool
47
+ def calculator(expression: str) -> str:
48
+ """Evaluate an arithmetic **expression** (e.g. "2 + 2*3").
49
+ Supported tokens: numbers, + ‑ * / ** % ( ), and constants/funcs from math.*
50
+ Returns the result or an error message.
51
+ """
52
+
53
+ allowed_names = {
54
+ k: v for k, v in math.__dict__.items() if not k.startswith("__")
55
+ }
56
+ try:
57
+ result = eval(expression, {"__builtins__": {}}, allowed_names)
58
+ return str(result)
59
+ except Exception as exc: # pylint: disable=broad-except
60
+ return f"Error: {exc}"
61
+
62
+
63
+ # ---------------------------------------------------------------------------
64
+ # Web search & Wikipedia -----------------------------------------------------
65
+ # ---------------------------------------------------------------------------
66
+
67
+ _DDG_URL = "https://duckduckgo.com/html/"
68
+ _WIKI_API = "https://en.wikipedia.org/api/rest_v1/page/summary/{}"
69
+
70
+
71
+ @tool
72
+ def web_search(query: str, max_results: int = 6) -> List[Dict[str, str]]:
73
+ """Return *max_results* DuckDuckGo hits for **query**.
74
+ Each hit is a dict with keys: title, url, snippet.
75
+ """
76
+ params = {"q": query, "s": "0"}
77
+ html = requests.post(_DDG_URL, data=params, timeout=10).text
78
+ soup = BeautifulSoup(html, "lxml")
79
+
80
+ results = []
81
+ for a in soup.select("a.result__a", limit=max_results):
82
+ title = _html_text(a)
83
+ url = a["href"]
84
+ snippet_tag = a.find_parent(class_="result").select_one(".result__snippet")
85
+ snippet = _html_text(snippet_tag) if snippet_tag else ""
86
+ results.append({"title": title, "url": url, "snippet": snippet})
87
+ return results
88
+
89
+
90
+ @tool
91
+ def wikipedia_summary(title: str) -> str:
92
+ """Return the lead paragraph of a Wikipedia page by **title**."""
93
+ url = _WIKI_API.format(requests.utils.quote(title))
94
+ resp = requests.get(url, timeout=10)
95
+ if resp.status_code != 200:
96
+ return f"Error: page '{title}' not found."
97
+ data = resp.json()
98
+ return data.get("extract", "No extract available.")
99
+
100
+
101
+ # ---------------------------------------------------------------------------
102
+ # YouTube metadata -----------------------------------------------------------
103
+ # ---------------------------------------------------------------------------
104
+
105
+ @tool
106
+ def youtube_info(url: str) -> Dict[str, Any]:
107
+ """Fetch basic metadata (title, length, author, views) of a YouTube video."""
108
+ try:
109
+ yt = YouTube(url)
110
+ except Exception as exc: # pylint: disable=broad-except
111
+ return {"error": str(exc)}
112
+ return {
113
+ "title": yt.title,
114
+ "author": yt.author,
115
+ "length_sec": yt.length,
116
+ "views": yt.views,
117
+ }
118
+
119
+
120
+ # ---------------------------------------------------------------------------
121
+ # Image inspection -----------------------------------------------------------
122
+ # ---------------------------------------------------------------------------
123
+
124
+ @tool
125
+ def image_info(path: str) -> Dict[str, Any]:
126
+ """Return basic stats for an image file at **path** (W×H, mode, format, mean
127
+ pixel value per channel)."""
128
+ p = pathlib.Path(path)
129
+ if not p.exists():
130
+ return {"error": "file not found"}
131
+
132
+ try:
133
+ with Image.open(p) as im:
134
+ pixels = list(im.getdata())
135
+ except Exception as exc: # pylint: disable=broad-except
136
+ return {"error": str(exc)}
137
+
138
+ # Flatten tuples (RGB) into list of channels
139
+ if isinstance(pixels[0], (tuple, list)):
140
+ channels = list(zip(*pixels))
141
+ means = [statistics.mean(c) for c in channels]
142
+ else:
143
+ means = [statistics.mean(pixels)]
144
+
145
+ return {
146
+ "width": im.width,
147
+ "height": im.height,
148
+ "format": im.format,
149
+ "mode": im.mode,
150
+ "mean_pixel": means,
151
+ }
152
+
153
+
154
+ # ---------------------------------------------------------------------------
155
+ # Excel inspection -----------------------------------------------------------
156
+ # ---------------------------------------------------------------------------
157
+
158
+ @tool
159
+ def excel_preview(path: str, sheet: str | int = 0, nrows: int = 5) -> str:
160
+ """Return the first *nrows* rows of an Excel sheet as a markdown table."""
161
+ p = pathlib.Path(path)
162
+ if not p.exists():
163
+ return "Error: file not found."
164
+
165
+ try:
166
+ df = pd.read_excel(p, sheet_name=sheet, engine="openpyxl", nrows=nrows)
167
+ except Exception as exc: # pylint: disable=broad-except
168
+ return f"Error: {exc}"
169
+
170
+ return df.to_markdown(index=False)
171
+
172
+
173
+ # ---------------------------------------------------------------------------
174
+ # Export list ----------------------------------------------------------------
175
+ # ---------------------------------------------------------------------------
176
+
177
+ TOOLS: List[BaseTool] = [
178
+ get_current_time,
179
+ calculator,
180
+ web_search,
181
+ wikipedia_summary,
182
+ youtube_info,
183
+ image_info,
184
+ excel_preview,
185
+ ]