gofannon 0.1.0__py3-none-any.whl → 0.25.10.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gofannon/arxiv/__init__.py +0 -2
- gofannon/base/__init__.py +4 -143
- gofannon/base/langchain.py +73 -0
- gofannon/base/smol_agents.py +49 -0
- gofannon/basic_math/__init__.py +1 -5
- gofannon/config.py +3 -1
- gofannon/github/__init__.py +0 -7
- gofannon/google_search/__init__.py +0 -0
- gofannon/google_search/google_search.py +55 -0
- gofannon/headless_browser/__init__.py +0 -0
- gofannon/headless_browser/base.py +42 -0
- gofannon/headless_browser/headless_browser_get.py +35 -0
- gofannon/open_notify_space/__init__.py +1 -0
- gofannon/open_notify_space/iss_locator.py +126 -0
- gofannon/reasoning/__init__.py +0 -3
- {gofannon-0.1.0.dist-info → gofannon-0.25.10.1.dist-info}/METADATA +19 -8
- {gofannon-0.1.0.dist-info → gofannon-0.25.10.1.dist-info}/RECORD +19 -10
- {gofannon-0.1.0.dist-info → gofannon-0.25.10.1.dist-info}/WHEEL +1 -1
- {gofannon-0.1.0.dist-info → gofannon-0.25.10.1.dist-info}/LICENSE +0 -0
gofannon/arxiv/__init__.py
CHANGED
gofannon/base/__init__.py
CHANGED
@@ -1,29 +1,14 @@
|
|
1
1
|
import time
|
2
2
|
from abc import ABC, abstractmethod
|
3
3
|
from dataclasses import dataclass
|
4
|
-
from typing import
|
4
|
+
from typing import Any, Callable
|
5
5
|
import json
|
6
6
|
import logging
|
7
7
|
from pathlib import Path
|
8
8
|
from ..config import ToolConfig
|
9
9
|
|
10
|
-
from
|
11
|
-
|
12
|
-
|
13
|
-
try:
|
14
|
-
from smolagents.tools import Tool as SmolTool
|
15
|
-
from smolagents.tools import tool as smol_tool_decorator
|
16
|
-
_HAS_SMOLAGENTS = True
|
17
|
-
except ImportError:
|
18
|
-
_HAS_SMOLAGENTS = False
|
19
|
-
|
20
|
-
try:
|
21
|
-
from langchain.tools import BaseTool as LangchainBaseTool
|
22
|
-
from langchain.pydantic_v1 import BaseModel, Field
|
23
|
-
from typing import Type, Optional
|
24
|
-
_HAS_LANGCHAIN = True
|
25
|
-
except ImportError:
|
26
|
-
_HAS_LANGCHAIN = False
|
10
|
+
from .smol_agents import SmolAgentsMixin
|
11
|
+
from .langchain import LangchainMixin
|
27
12
|
|
28
13
|
@dataclass
|
29
14
|
class ToolResult:
|
@@ -73,7 +58,7 @@ class WorkflowContext:
|
|
73
58
|
}
|
74
59
|
self.execution_log.append(entry)
|
75
60
|
|
76
|
-
class BaseTool(ABC):
|
61
|
+
class BaseTool(SmolAgentsMixin, LangchainMixin, ABC):
|
77
62
|
def __init__(self, **kwargs):
|
78
63
|
self.logger = logging.getLogger(f"{self.__class__.__module__}.{self.__class__.__name__}")
|
79
64
|
self._load_config()
|
@@ -125,127 +110,3 @@ class BaseTool(ABC):
|
|
125
110
|
error=str(e),
|
126
111
|
retryable=True
|
127
112
|
)
|
128
|
-
|
129
|
-
def import_from_smolagents(self, smol_tool: "SmolTool"):
|
130
|
-
"""
|
131
|
-
Takes a smolagents Tool instance and adapts it into this Tool.
|
132
|
-
"""
|
133
|
-
if not _HAS_SMOLAGENTS:
|
134
|
-
raise RuntimeError(
|
135
|
-
"smolagents is not installed or could not be imported. "
|
136
|
-
"Install it or check your environment."
|
137
|
-
)
|
138
|
-
self.name = smol_tool.name[0]
|
139
|
-
self.description = smol_tool.description #getattr(smol_tool, "description", "No description provided.")
|
140
|
-
|
141
|
-
|
142
|
-
def adapted_fn(*args, **kwargs):
|
143
|
-
return smol_tool.forward(*args, **kwargs)
|
144
|
-
|
145
|
-
|
146
|
-
self.fn = adapted_fn
|
147
|
-
|
148
|
-
def export_to_smolagents(self) -> "SmolTool":
|
149
|
-
"""
|
150
|
-
Export this Tool as a smolagents Tool instance.
|
151
|
-
This sets up a smolagents-style forward method that calls self.fn.
|
152
|
-
"""
|
153
|
-
if not _HAS_SMOLAGENTS:
|
154
|
-
raise RuntimeError(
|
155
|
-
"smolagents is not installed or could not be imported. "
|
156
|
-
"Install it or check your environment."
|
157
|
-
)
|
158
|
-
|
159
|
-
# Provide a standard forward function that calls self.fn
|
160
|
-
def smol_forward(*args, **kwargs):
|
161
|
-
return self.fn(*args, **kwargs)
|
162
|
-
|
163
|
-
|
164
|
-
inputs_definition = {
|
165
|
-
"example_arg": {
|
166
|
-
"type": "string",
|
167
|
-
"description": "Example argument recognized by this tool"
|
168
|
-
}
|
169
|
-
}
|
170
|
-
output_type = "string"
|
171
|
-
|
172
|
-
# Construct a new smolagents Tool with the minimal fields
|
173
|
-
exported_tool = SmolTool()
|
174
|
-
exported_tool.name = getattr(self, "name", "exported_base_tool")
|
175
|
-
exported_tool.description = getattr(self, "description", "Exported from Tool")
|
176
|
-
exported_tool.inputs = inputs_definition
|
177
|
-
exported_tool.output_type = output_type
|
178
|
-
exported_tool.forward = smol_forward
|
179
|
-
exported_tool.is_initialized = True
|
180
|
-
|
181
|
-
return exported_tool
|
182
|
-
|
183
|
-
def import_from_langchain(self, langchain_tool: "LangchainBaseTool"):
|
184
|
-
if not _HAS_LANGCHAIN:
|
185
|
-
raise RuntimeError("langchain is not installed. Install with `pip install langchain-core`")
|
186
|
-
|
187
|
-
self.name = getattr(langchain_tool, "name", "exported_langchain_tool")
|
188
|
-
self.description = getattr(langchain_tool, "description", "No description provided.")
|
189
|
-
|
190
|
-
maybe_args_schema = getattr(langchain_tool, "args_schema", None)
|
191
|
-
if maybe_args_schema and hasattr(maybe_args_schema, "schema") and callable(maybe_args_schema.schema):
|
192
|
-
args_schema = maybe_args_schema.schema()
|
193
|
-
else:
|
194
|
-
args_schema = {}
|
195
|
-
|
196
|
-
# Store parameters to avoid modifying the definition property directly
|
197
|
-
self._parameters = args_schema.get("properties", {})
|
198
|
-
self._required = args_schema.get("required", [])
|
199
|
-
|
200
|
-
# Adapt the LangChain tool's execution method
|
201
|
-
def adapted_fn(*args, **kwargs):
|
202
|
-
return langchain_tool._run(*args, **kwargs)
|
203
|
-
|
204
|
-
self.fn = adapted_fn
|
205
|
-
|
206
|
-
def export_to_langchain(self) -> "LangchainBaseTool":
|
207
|
-
if not _HAS_LANGCHAIN:
|
208
|
-
raise RuntimeError(
|
209
|
-
"langchain is not installed. Install with `pip install langchain-core`"
|
210
|
-
)
|
211
|
-
|
212
|
-
from pydantic import create_model
|
213
|
-
|
214
|
-
# Create type mapping from JSON schema types to Python types
|
215
|
-
type_map = {
|
216
|
-
"number": float,
|
217
|
-
"string": str,
|
218
|
-
"integer": int,
|
219
|
-
"boolean": bool,
|
220
|
-
"object": dict,
|
221
|
-
"array": list
|
222
|
-
}
|
223
|
-
|
224
|
-
parameters = self.definition.get("function", {}).get("parameters", {})
|
225
|
-
param_properties = parameters.get("properties", {})
|
226
|
-
|
227
|
-
# Dynamically create ArgsSchema using pydantic.create_model
|
228
|
-
fields = {}
|
229
|
-
for param_name, param_def in param_properties.items():
|
230
|
-
param_type = param_def.get("type", "string")
|
231
|
-
description = param_def.get("description", "")
|
232
|
-
fields[param_name] = (
|
233
|
-
type_map.get(param_type, str),
|
234
|
-
Field(..., description=description)
|
235
|
-
)
|
236
|
-
|
237
|
-
ArgsSchema = create_model('ArgsSchema', **fields)
|
238
|
-
|
239
|
-
# Create tool subclass with our functionality
|
240
|
-
class ExportedTool(LangchainBaseTool):
|
241
|
-
name: str = self.definition.get("function", {}).get("name", "")
|
242
|
-
description: str = self.definition.get("function", {}).get("description", "")
|
243
|
-
args_schema: Type[BaseModel] = ArgsSchema
|
244
|
-
fn: Callable = self.fn
|
245
|
-
|
246
|
-
def _run(self, *args, **kwargs):
|
247
|
-
return self.fn(*args, **kwargs)
|
248
|
-
|
249
|
-
# Instantiate and return the tool
|
250
|
-
tool = ExportedTool()
|
251
|
-
return tool
|
@@ -0,0 +1,73 @@
|
|
1
|
+
from typing import Type, Callable
|
2
|
+
|
3
|
+
try:
|
4
|
+
from langchain.tools import BaseTool as LangchainBaseTool
|
5
|
+
from langchain.pydantic_v1 import BaseModel, Field
|
6
|
+
_HAS_LANGCHAIN = True
|
7
|
+
except ImportError:
|
8
|
+
_HAS_LANGCHAIN = False
|
9
|
+
|
10
|
+
class LangchainMixin:
|
11
|
+
def import_from_langchain(self, langchain_tool: LangchainBaseTool):
|
12
|
+
if not _HAS_LANGCHAIN:
|
13
|
+
raise RuntimeError("langchain is not installed. Install with `pip install langchain-core`")
|
14
|
+
|
15
|
+
self.name = getattr(langchain_tool, "name", "exported_langchain_tool")
|
16
|
+
self.description = getattr(langchain_tool, "description", "No description provided.")
|
17
|
+
|
18
|
+
maybe_args_schema = getattr(langchain_tool, "args_schema", None)
|
19
|
+
if maybe_args_schema and hasattr(maybe_args_schema, "schema") and callable(maybe_args_schema.schema):
|
20
|
+
args_schema = maybe_args_schema.schema()
|
21
|
+
else:
|
22
|
+
args_schema = {}
|
23
|
+
|
24
|
+
self._parameters = args_schema.get("properties", {})
|
25
|
+
self._required = args_schema.get("required", [])
|
26
|
+
|
27
|
+
def adapted_fn(*args, **kwargs):
|
28
|
+
return langchain_tool._run(*args, **kwargs)
|
29
|
+
|
30
|
+
self.fn = adapted_fn
|
31
|
+
|
32
|
+
def export_to_langchain(self) -> LangchainBaseTool:
|
33
|
+
if not _HAS_LANGCHAIN:
|
34
|
+
raise RuntimeError(
|
35
|
+
"langchain is not installed. Install with `pip install langchain-core`"
|
36
|
+
)
|
37
|
+
|
38
|
+
from pydantic import create_model
|
39
|
+
|
40
|
+
type_map = {
|
41
|
+
"number": float,
|
42
|
+
"string": str,
|
43
|
+
"integer": int,
|
44
|
+
"boolean": bool,
|
45
|
+
"object": dict,
|
46
|
+
"array": list
|
47
|
+
}
|
48
|
+
|
49
|
+
parameters = self.definition.get("function", {}).get("parameters", {})
|
50
|
+
param_properties = parameters.get("properties", {})
|
51
|
+
|
52
|
+
fields = {}
|
53
|
+
for param_name, param_def in param_properties.items():
|
54
|
+
param_type = param_def.get("type", "string")
|
55
|
+
description = param_def.get("description", "")
|
56
|
+
fields[param_name] = (
|
57
|
+
type_map.get(param_type, str),
|
58
|
+
Field(..., description=description)
|
59
|
+
)
|
60
|
+
|
61
|
+
ArgsSchema = create_model('ArgsSchema', **fields)
|
62
|
+
|
63
|
+
class ExportedTool(LangchainBaseTool):
|
64
|
+
name: str = self.definition.get("function", {}).get("name", "")
|
65
|
+
description: str = self.definition.get("function", {}).get("description", "")
|
66
|
+
args_schema: Type[BaseModel] = ArgsSchema
|
67
|
+
fn: Callable = self.fn
|
68
|
+
|
69
|
+
def _run(self, *args, **kwargs):
|
70
|
+
return self.fn(*args, **kwargs)
|
71
|
+
|
72
|
+
tool = ExportedTool()
|
73
|
+
return tool
|
@@ -0,0 +1,49 @@
|
|
1
|
+
try:
|
2
|
+
from smolagents.tools import Tool as SmolTool
|
3
|
+
from smolagents.tools import tool as smol_tool_decorator
|
4
|
+
_HAS_SMOLAGENTS = True
|
5
|
+
except ImportError:
|
6
|
+
_HAS_SMOLAGENTS = False
|
7
|
+
|
8
|
+
class SmolAgentsMixin:
|
9
|
+
def import_from_smolagents(self, smol_tool: SmolTool):
|
10
|
+
if not _HAS_SMOLAGENTS:
|
11
|
+
raise RuntimeError(
|
12
|
+
"smolagents is not installed or could not be imported. "
|
13
|
+
"Install it or check your environment."
|
14
|
+
)
|
15
|
+
self.name = smol_tool.name[0]
|
16
|
+
self.description = smol_tool.description
|
17
|
+
|
18
|
+
def adapted_fn(*args, **kwargs):
|
19
|
+
return smol_tool.forward(*args, **kwargs)
|
20
|
+
|
21
|
+
self.fn = adapted_fn
|
22
|
+
|
23
|
+
def export_to_smolagents(self) -> SmolTool:
|
24
|
+
if not _HAS_SMOLAGENTS:
|
25
|
+
raise RuntimeError(
|
26
|
+
"smolagents is not installed or could not be imported. "
|
27
|
+
"Install it or check your environment."
|
28
|
+
)
|
29
|
+
|
30
|
+
def smol_forward(*args, **kwargs):
|
31
|
+
return self.fn(*args, **kwargs)
|
32
|
+
|
33
|
+
inputs_definition = {
|
34
|
+
"example_arg": {
|
35
|
+
"type": "string",
|
36
|
+
"description": "Example argument recognized by this tool"
|
37
|
+
}
|
38
|
+
}
|
39
|
+
output_type = "string"
|
40
|
+
|
41
|
+
exported_tool = SmolTool()
|
42
|
+
exported_tool.name = getattr(self, "name", "exported_base_tool")
|
43
|
+
exported_tool.description = getattr(self, "description", "Exported from Tool")
|
44
|
+
exported_tool.inputs = inputs_definition
|
45
|
+
exported_tool.output_type = output_type
|
46
|
+
exported_tool.forward = smol_forward
|
47
|
+
exported_tool.is_initialized = True
|
48
|
+
|
49
|
+
return exported_tool
|
gofannon/basic_math/__init__.py
CHANGED
gofannon/config.py
CHANGED
@@ -11,7 +11,9 @@ class ToolConfig:
|
|
11
11
|
self.config = {
|
12
12
|
'github_api_key': os.getenv('GITHUB_API_KEY'),
|
13
13
|
'deepinfra_api_key': os.getenv('DEEPINFRA_API_KEY'),
|
14
|
-
'arxiv_api_key': os.getenv('ARXIV_API_KEY')
|
14
|
+
'arxiv_api_key': os.getenv('ARXIV_API_KEY'),
|
15
|
+
'google_search_api_key': os.getenv('GOOGLE_SEARCH_API_KEY'),
|
16
|
+
'google_search_engine_id': os.getenv('GOOGLE_SEARCH_ENGINE_ID')
|
15
17
|
}
|
16
18
|
|
17
19
|
@classmethod
|
gofannon/github/__init__.py
CHANGED
File without changes
|
@@ -0,0 +1,55 @@
|
|
1
|
+
from ..base import BaseTool
|
2
|
+
from googleapiclient.discovery import build
|
3
|
+
from ..config import ToolConfig, FunctionRegistry
|
4
|
+
import logging
|
5
|
+
|
6
|
+
logger = logging.getLogger(__name__)
|
7
|
+
|
8
|
+
@FunctionRegistry.register
|
9
|
+
class GoogleSearch(BaseTool):
|
10
|
+
def __init__(self, api_key=None, engine_id=None, name="google_search"):
|
11
|
+
super().__init__()
|
12
|
+
self.api_key = api_key or ToolConfig.get("google_search_api_key")
|
13
|
+
self.engine_id = engine_id or ToolConfig.get("google_search_engine_id")
|
14
|
+
self.name = name
|
15
|
+
self.API_SERVICE = 'google_search'
|
16
|
+
|
17
|
+
@property
|
18
|
+
def definition(self):
|
19
|
+
return {
|
20
|
+
"type": "function",
|
21
|
+
"function": {
|
22
|
+
"name": self.name,
|
23
|
+
"description": "Searches Google for the given query and returns snippets from the results.",
|
24
|
+
"parameters": {
|
25
|
+
"type": "object",
|
26
|
+
"properties": {
|
27
|
+
"query": {
|
28
|
+
"type": "string",
|
29
|
+
"description": "The search query."
|
30
|
+
},
|
31
|
+
"num_results": {
|
32
|
+
"type": "integer",
|
33
|
+
"description": "The maximum number of results to return (default: 5)."
|
34
|
+
}
|
35
|
+
},
|
36
|
+
"required": ["query"]
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
def fn(self, query, num_results=5):
|
42
|
+
logger.debug(f"Searching Google for: {query}")
|
43
|
+
try:
|
44
|
+
service = build("customsearch", "v1", developerKey=self.api_key)
|
45
|
+
cse = service.cse()
|
46
|
+
result = cse.list(q=query, cx=self.engine_id, num=num_results).execute()
|
47
|
+
|
48
|
+
search_results = []
|
49
|
+
for item in result['items']:
|
50
|
+
search_results.append(f"Title: {item['title']}\nSnippet: {item['snippet']}\nLink: {item['link']}")
|
51
|
+
return "\n\n".join(search_results)
|
52
|
+
|
53
|
+
except Exception as e:
|
54
|
+
logger.error(f"Error during Google Search: {e}")
|
55
|
+
return f"Error during Google Search: {e}"
|
File without changes
|
@@ -0,0 +1,42 @@
|
|
1
|
+
from selenium import webdriver
|
2
|
+
from selenium.webdriver.chrome.options import Options
|
3
|
+
from ..base import BaseTool
|
4
|
+
import logging
|
5
|
+
|
6
|
+
logger = logging.getLogger(__name__)
|
7
|
+
|
8
|
+
class HeadlessBrowserBase(BaseTool):
|
9
|
+
"""
|
10
|
+
Base class for headless browser tools.
|
11
|
+
On initialization, the provider parameter may be one of:
|
12
|
+
"selenium-chrome", "selenium-firefox", "lightpanda", or "remote".
|
13
|
+
Currently, only "selenium-chrome" is supported.
|
14
|
+
"""
|
15
|
+
def __init__(self, provider="selenium-chrome", **kwargs):
|
16
|
+
super().__init__(**kwargs)
|
17
|
+
self.provider = provider.lower()
|
18
|
+
supported = ["selenium-chrome", "selenium-firefox", "lightpanda", "remote"]
|
19
|
+
if self.provider not in supported:
|
20
|
+
raise ValueError(f"Unsupported provider: {self.provider}. Supported providers: {supported}")
|
21
|
+
|
22
|
+
def _get_driver(self):
|
23
|
+
if self.provider == "selenium-chrome":
|
24
|
+
chrome_options = Options()
|
25
|
+
chrome_options.add_argument("--headless")
|
26
|
+
chrome_options.add_argument("--disable-gpu")
|
27
|
+
chrome_options.add_argument("--no-sandbox")
|
28
|
+
# Adjust the executable_path if needed or ensure the chromedriver is in PATH.
|
29
|
+
driver = webdriver.Chrome(options=chrome_options)
|
30
|
+
return driver
|
31
|
+
else:
|
32
|
+
raise NotImplementedError(f"Provider {self.provider} is not supported in the current implementation.")
|
33
|
+
|
34
|
+
def get_page_source(self, url):
|
35
|
+
driver = self._get_driver()
|
36
|
+
try:
|
37
|
+
driver.get(url)
|
38
|
+
# Optionally, add waits here if needed so that JavaScript can fully execute.
|
39
|
+
page_source = driver.page_source
|
40
|
+
finally:
|
41
|
+
driver.quit()
|
42
|
+
return page_source
|
@@ -0,0 +1,35 @@
|
|
1
|
+
from .base import HeadlessBrowserBase
|
2
|
+
from ..config import FunctionRegistry
|
3
|
+
import logging
|
4
|
+
|
5
|
+
logger = logging.getLogger(__name__)
|
6
|
+
|
7
|
+
@FunctionRegistry.register
|
8
|
+
class HeadlessBrowserGet(HeadlessBrowserBase):
|
9
|
+
def __init__(self, provider="selenium-chrome", name="headless_browser_get"):
|
10
|
+
super().__init__(provider=provider)
|
11
|
+
self.name = name
|
12
|
+
|
13
|
+
@property
|
14
|
+
def definition(self):
|
15
|
+
return {
|
16
|
+
"type": "function",
|
17
|
+
"function": {
|
18
|
+
"name": self.name,
|
19
|
+
"description": "Retrieve the contents of a web page with JavaScript rendered using a headless browser.",
|
20
|
+
"parameters": {
|
21
|
+
"type": "object",
|
22
|
+
"properties": {
|
23
|
+
"url": {
|
24
|
+
"type": "string",
|
25
|
+
"description": "The URL of the web page to fetch"
|
26
|
+
}
|
27
|
+
},
|
28
|
+
"required": ["url"]
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
def fn(self, url):
|
34
|
+
logger.debug(f"Fetching URL with headless browser using provider {self.provider}: {url}")
|
35
|
+
return self.get_page_source(url)
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1,126 @@
|
|
1
|
+
import jsonschema
|
2
|
+
import jsonschema.exceptions
|
3
|
+
from ..base import BaseTool
|
4
|
+
from ..config import FunctionRegistry
|
5
|
+
|
6
|
+
import logging
|
7
|
+
import json
|
8
|
+
|
9
|
+
import requests
|
10
|
+
from jsonschema import validate
|
11
|
+
|
12
|
+
logger = logging.getLogger(__name__)
|
13
|
+
|
14
|
+
valid_iss_schema = {
|
15
|
+
"type": "object",
|
16
|
+
"properties": {
|
17
|
+
"message": {"type": "string", "enum": ["success"]},
|
18
|
+
"timestamp": {"type": "integer"},
|
19
|
+
"iss_position": {
|
20
|
+
"type": "object",
|
21
|
+
"properties": {
|
22
|
+
"longitude": {"type": "string"},
|
23
|
+
"latitude": {"type": "string"},
|
24
|
+
},
|
25
|
+
"required": ["longitude", "latitude"],
|
26
|
+
},
|
27
|
+
},
|
28
|
+
"required": ["message", "timestamp", "iss_position"],
|
29
|
+
}
|
30
|
+
|
31
|
+
error_response_string = "Error: The ISS endpoint returned an error. No location for the ISS can be determined"
|
32
|
+
error_response_json = {
|
33
|
+
"message": "failure",
|
34
|
+
"error": "Error: The ISS endpoint returned an error. No location for the ISS can be determined",
|
35
|
+
}
|
36
|
+
|
37
|
+
|
38
|
+
@FunctionRegistry.register
|
39
|
+
class IssLocator(BaseTool):
|
40
|
+
def __init__(self, name="iss_locator", format_json=True):
|
41
|
+
super().__init__()
|
42
|
+
self.name = name
|
43
|
+
self.format_json = format_json
|
44
|
+
|
45
|
+
@property
|
46
|
+
def definition(self):
|
47
|
+
return {
|
48
|
+
"type": "function",
|
49
|
+
"function": {
|
50
|
+
"name": self.name,
|
51
|
+
"description": "Returns the latitude / longitude of the current location of the International Space Station (ISS)",
|
52
|
+
"parameters": {},
|
53
|
+
"required": [],
|
54
|
+
},
|
55
|
+
}
|
56
|
+
|
57
|
+
# Function returns one of two messages, depending on the requested format:
|
58
|
+
#
|
59
|
+
# With format_json=False, Returns one of two strings:
|
60
|
+
# "According to OpenNotify.org, the International Space Station can be found at (lat, long) (x,y)"
|
61
|
+
# or
|
62
|
+
# "The ISS endpoint returned an error. No location for the ISS can be determined"
|
63
|
+
#
|
64
|
+
# With format_json=True (default), the following strings:
|
65
|
+
# "{
|
66
|
+
# "message": "success",
|
67
|
+
# "timestamp": 1739999640,
|
68
|
+
# "iss_position": {"longitude": "-11.6885", "latitude": "-50.0654"},
|
69
|
+
# }"
|
70
|
+
# or
|
71
|
+
# "{
|
72
|
+
# "message": "failure",
|
73
|
+
# "error": "Error: The ISS endpoint returned an error. No location for the ISS can be determined",
|
74
|
+
# }"
|
75
|
+
|
76
|
+
def fn(self):
|
77
|
+
base_url = "http://api.open-notify.org/iss-now.json"
|
78
|
+
logger.debug(f"Fetching ISS pos from OpenNotify.org at {base_url}")
|
79
|
+
if self.format_json:
|
80
|
+
response = json.dumps(error_response_json)
|
81
|
+
else:
|
82
|
+
response = error_response_string
|
83
|
+
|
84
|
+
try:
|
85
|
+
http_response = requests.get(base_url)
|
86
|
+
response_json = http_response.json()
|
87
|
+
# Validate the returned schema is valid.
|
88
|
+
validate(response_json, valid_iss_schema)
|
89
|
+
# Does not seem to be a way to evaluate strings as floats in a range in jsonschema,
|
90
|
+
# other than using a REALLY ugly regex.
|
91
|
+
lat = float(response_json["iss_position"]["latitude"])
|
92
|
+
long = float(response_json["iss_position"]["longitude"])
|
93
|
+
if (lat > -90 and lat < 90) and (long > -180 and long < 180):
|
94
|
+
if self.format_json:
|
95
|
+
response = json.dumps(response_json)
|
96
|
+
else:
|
97
|
+
response = f"According to OpenNotify.org, the International Space Station can be found at (lat, long) ({lat}, {long})"
|
98
|
+
else:
|
99
|
+
raise ValueError(f"(latitude, longitude) out of range: ({lat},{long})")
|
100
|
+
except requests.exceptions.HTTPError as errh:
|
101
|
+
logger.debug(f"HTTP exception: GET at {base_url} returns {errh}")
|
102
|
+
pass
|
103
|
+
except requests.exceptions.ConnectionError as errc:
|
104
|
+
logger.debug(f"HTTP connection exception: GET at {base_url} returns {errc}")
|
105
|
+
pass
|
106
|
+
except requests.exceptions.Timeout as errt:
|
107
|
+
logger.debug(f"HTTP timeout exception: GET at {base_url} returns {errt}")
|
108
|
+
pass
|
109
|
+
except requests.exceptions.RequestException as err:
|
110
|
+
logger.debug(f"Requests exception: GET at {base_url} returns {err}")
|
111
|
+
pass
|
112
|
+
except jsonschema.exceptions.ValidationError as errj:
|
113
|
+
logger.debug(
|
114
|
+
f"JSON validation failure GET at {base_url} malformed response: {errj}"
|
115
|
+
)
|
116
|
+
pass
|
117
|
+
except ValueError as errv:
|
118
|
+
logger.debug(
|
119
|
+
f"Value Exception GET at {base_url} malformed response: {errv}"
|
120
|
+
)
|
121
|
+
pass
|
122
|
+
except Exception as erre:
|
123
|
+
logger.debug(f"General exception GET at {base_url} Error: {erre}")
|
124
|
+
pass
|
125
|
+
|
126
|
+
return response
|
gofannon/reasoning/__init__.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: gofannon
|
3
|
-
Version: 0.1
|
3
|
+
Version: 0.25.10.1
|
4
4
|
Summary: A collection of tools for LLMs
|
5
5
|
License: ASFv2
|
6
6
|
Author: Trevor Grant
|
@@ -10,14 +10,25 @@ Classifier: License :: Other/Proprietary License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
11
11
|
Classifier: Programming Language :: Python :: 3.10
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
15
|
+
Provides-Extra: google
|
16
|
+
Provides-Extra: headless-browser
|
17
|
+
Provides-Extra: langchain
|
18
|
+
Provides-Extra: smolagents
|
19
|
+
Provides-Extra: testing
|
13
20
|
Requires-Dist: GitPython (>=3.1.43,<4.0.0)
|
14
|
-
Requires-Dist:
|
21
|
+
Requires-Dist: google-api-python-client (>=2.161.0,<3.0.0) ; extra == "google"
|
22
|
+
Requires-Dist: jsonschema (>=4.23.0,<5.0.0)
|
23
|
+
Requires-Dist: langchain (>=0.3.16,<0.4.0) ; extra == "langchain"
|
15
24
|
Requires-Dist: openai (>=1.60.2,<2.0.0)
|
16
|
-
Requires-Dist: pydantic (>=2.10.6,<3.0.0)
|
17
|
-
Requires-Dist: pytest (>=8.3.4,<9.0.0)
|
25
|
+
Requires-Dist: pydantic (>=2.10.6,<3.0.0) ; extra == "langchain"
|
26
|
+
Requires-Dist: pytest (>=8.3.4,<9.0.0) ; extra == "testing"
|
18
27
|
Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
19
28
|
Requires-Dist: requests (>=2.32.3,<3.0.0)
|
20
|
-
Requires-Dist:
|
29
|
+
Requires-Dist: requests-mock (>=1.12.1,<2.0.0) ; extra == "testing"
|
30
|
+
Requires-Dist: selenium (>=4.10.0,<5.0.0) ; extra == "headless-browser"
|
31
|
+
Requires-Dist: smolagents (>=1.6.0,<2.0.0) ; extra == "smolagents"
|
21
32
|
Description-Content-Type: text/markdown
|
22
33
|
|
23
34
|

|
@@ -59,7 +70,7 @@ Each tool comes with its own documentation, which can be found in the `docs/` di
|
|
59
70
|
To install gofannon, simply clone the repository and install the required dependencies:
|
60
71
|
|
61
72
|
```bash
|
62
|
-
git clone https://github.com/
|
73
|
+
git clone https://github.com/The-AI-Alliance/gofannon.git
|
63
74
|
cd gofannon
|
64
75
|
pip install -r requirements.txt
|
65
76
|
```
|
@@ -67,7 +78,7 @@ pip install -r requirements.txt
|
|
67
78
|
or
|
68
79
|
|
69
80
|
```
|
70
|
-
pip install git+https://github.com/
|
81
|
+
pip install git+https://github.com/The-AI-Alliance/gofannon.git
|
71
82
|
```
|
72
83
|
|
73
84
|
## License
|
@@ -1,32 +1,41 @@
|
|
1
1
|
gofannon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
gofannon/arxiv/__init__.py,sha256=
|
2
|
+
gofannon/arxiv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
gofannon/arxiv/get_article.py,sha256=SRGTXFXdXdXTIOLZKWUTXxZEYEqZFWFJEV2nTsU5qqU,1167
|
4
4
|
gofannon/arxiv/search.py,sha256=37Zx1y2vAX1xYIKaAxzBGXE3qPHUZdAD2XR0H1Acs-4,4225
|
5
|
-
gofannon/base/__init__.py,sha256=
|
6
|
-
gofannon/
|
5
|
+
gofannon/base/__init__.py,sha256=Bsjc0ZJkVRx_q7f6Pp6czgkiysyTRwmqCZIflX7xeqA,3396
|
6
|
+
gofannon/base/langchain.py,sha256=JbktMQQuMr2LmmGDKU4aDPTnBJZ39_UPChXiB9m3eUM,2619
|
7
|
+
gofannon/base/smol_agents.py,sha256=8jOK7ijpQ7JjXrk1No6baOmw7PD6FmHLgfXrNX5iJ2E,1672
|
8
|
+
gofannon/basic_math/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
7
9
|
gofannon/basic_math/addition.py,sha256=zA-xtUBNnGnQVqTJkBvjZwX0gnGZ6mrUGhrlTbsH1ts,1148
|
8
10
|
gofannon/basic_math/division.py,sha256=ZO8ZzWNL9zeFdXTEdPWDpnbDrWMXVeucSu105RbQmWU,1229
|
9
11
|
gofannon/basic_math/exponents.py,sha256=w4qDlFZ9M1lf6X-tjG-ndpECfCOS7Qtc_VLICw0oh2w,1205
|
10
12
|
gofannon/basic_math/multiplication.py,sha256=PJ5sKWMCVlBaTeZ_j3gwYOEQXAhN-qIXhnrNcyhWGKM,1168
|
11
13
|
gofannon/basic_math/subtraction.py,sha256=gM1_N1mZ3qAXC6qnkzfijKXiOx27Gg93-CaB_ifMbOQ,1164
|
12
14
|
gofannon/cli.py,sha256=-T-jjBNl_74TsGRcrjxsQnG0-wA2neYhncnaqCiEzPo,1733
|
13
|
-
gofannon/config.py,sha256=
|
14
|
-
gofannon/github/__init__.py,sha256=
|
15
|
+
gofannon/config.py,sha256=N1xmWTbcyDPZT3r_ZuwW1RI0VRhDcbf3qIasEZZNwyc,1718
|
16
|
+
gofannon/github/__init__.py,sha256=VFw4sJIt4Zc0-__eYnksN8Ku9qMhbPpHJEkXMWUiD30,4
|
15
17
|
gofannon/github/commit_file.py,sha256=jdQGQHbrZx4521XgTbx5N0Ss8fDyl7hvp9sjDW15v9U,2573
|
16
18
|
gofannon/github/commit_files.py,sha256=0WP4nx4RYpO_Vb45Sa65afuzSMf4de-Wt6awpSOusyM,4395
|
17
19
|
gofannon/github/create_issue.py,sha256=WXq0klzPvGZnZyZRmriGOkHl7E_Tp08vO1v2ou7TR8w,2560
|
18
20
|
gofannon/github/get_repo_contents.py,sha256=9k6M2BqGlNsSGVjyfW7nxZpk1TFuhyPoZvURkv1PEyo,3637
|
19
21
|
gofannon/github/read_issue.py,sha256=JrnBAlZxknhHm3aLC0uB9u0bSvoQNfK3OKmxYlr8jgQ,2308
|
20
22
|
gofannon/github/search.py,sha256=yuX_dZ6f8ogUnskIRMUgF8wuN7JepqRtTDFrbmbwrrs,2183
|
23
|
+
gofannon/google_search/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
|
+
gofannon/google_search/google_search.py,sha256=WRaGSLoeZjy5Qtn89Sp01nNugiGI0NL1ZEdE1ebghl4,2100
|
25
|
+
gofannon/headless_browser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
|
+
gofannon/headless_browser/base.py,sha256=bgvBvkTNCqRnhC8Ffc6oZ3yoxpOl6fkAq0doDKnQtt8,1721
|
27
|
+
gofannon/headless_browser/headless_browser_get.py,sha256=kOnHxfoZayfCuS6OKloLdwxehiInwcd5dM0HbKAeM5U,1182
|
21
28
|
gofannon/nhsta/__init__.py,sha256=jTV6arXumVgJagKOq6GnYhHwcX9t7Jjqq5JvsE5-zxQ,1925
|
29
|
+
gofannon/open_notify_space/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
30
|
+
gofannon/open_notify_space/iss_locator.py,sha256=STLNSD5HriRR6grpRpiTRDbqVRtWMPVoGuV8SygHGNY,4734
|
22
31
|
gofannon/orchestration/__init__.py,sha256=_p_XhWHgOIgiamFSGwFUqrnBlIYDvQMq5L5mxJvxiks,5121
|
23
32
|
gofannon/orchestration/firebase_wrapper.py,sha256=jXqUcIoKuTC_1ZffN3v1DN9X6of-OuMKWP8ZzQ-wHOU,1394
|
24
|
-
gofannon/reasoning/__init__.py,sha256=
|
33
|
+
gofannon/reasoning/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
34
|
gofannon/reasoning/base.py,sha256=D-4JHJqUlqgwMNOkKU0BHYA4GEWwNgPlLxKYHX0FVyg,1494
|
26
35
|
gofannon/reasoning/hierarchical_cot.py,sha256=e8ZgMbyJQ0wCBEmv7QJqFv7l3XxTMwDYupGxJ7EF6t8,11516
|
27
36
|
gofannon/reasoning/sequential_cot.py,sha256=m9c8GnyTtmI-JntCuhkoFfULAabVOxsYgTRUd3MjzfY,3166
|
28
37
|
gofannon/reasoning/tree_of_thought.py,sha256=TRhRJQNsFVauCLw4TOvQCDcX1nGmp_wSg9H67GJn1hs,10574
|
29
|
-
gofannon-0.1.
|
30
|
-
gofannon-0.1.
|
31
|
-
gofannon-0.1.
|
32
|
-
gofannon-0.1.
|
38
|
+
gofannon-0.25.10.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
39
|
+
gofannon-0.25.10.1.dist-info/METADATA,sha256=rP0KpQfrea01Rl4cTtYfyLCByLPjojDlleY_9lyU6QQ,3884
|
40
|
+
gofannon-0.25.10.1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
41
|
+
gofannon-0.25.10.1.dist-info/RECORD,,
|
File without changes
|