gofannon 0.1.0__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/__init__.py +0 -0
- gofannon/arxiv/__init__.py +2 -0
- gofannon/arxiv/get_article.py +41 -0
- gofannon/arxiv/search.py +115 -0
- gofannon/base/__init__.py +251 -0
- gofannon/basic_math/__init__.py +5 -0
- gofannon/basic_math/addition.py +39 -0
- gofannon/basic_math/division.py +41 -0
- gofannon/basic_math/exponents.py +39 -0
- gofannon/basic_math/multiplication.py +39 -0
- gofannon/basic_math/subtraction.py +39 -0
- gofannon/cli.py +53 -0
- gofannon/config.py +58 -0
- gofannon/github/__init__.py +11 -0
- gofannon/github/commit_file.py +77 -0
- gofannon/github/commit_files.py +116 -0
- gofannon/github/create_issue.py +78 -0
- gofannon/github/get_repo_contents.py +98 -0
- gofannon/github/read_issue.py +70 -0
- gofannon/github/search.py +67 -0
- gofannon/nhsta/__init__.py +59 -0
- gofannon/orchestration/__init__.py +144 -0
- gofannon/orchestration/firebase_wrapper.py +42 -0
- gofannon/reasoning/__init__.py +3 -0
- gofannon/reasoning/base.py +47 -0
- gofannon/reasoning/hierarchical_cot.py +272 -0
- gofannon/reasoning/sequential_cot.py +77 -0
- gofannon/reasoning/tree_of_thought.py +256 -0
- gofannon-0.1.0.dist-info/LICENSE +201 -0
- gofannon-0.1.0.dist-info/METADATA +84 -0
- gofannon-0.1.0.dist-info/RECORD +32 -0
- gofannon-0.1.0.dist-info/WHEEL +4 -0
gofannon/config.py
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
import os
|
2
|
+
from dotenv import load_dotenv
|
3
|
+
import logging
|
4
|
+
|
5
|
+
|
6
|
+
class ToolConfig:
|
7
|
+
_instance = None
|
8
|
+
|
9
|
+
def __init__(self):
|
10
|
+
load_dotenv()
|
11
|
+
self.config = {
|
12
|
+
'github_api_key': os.getenv('GITHUB_API_KEY'),
|
13
|
+
'deepinfra_api_key': os.getenv('DEEPINFRA_API_KEY'),
|
14
|
+
'arxiv_api_key': os.getenv('ARXIV_API_KEY')
|
15
|
+
}
|
16
|
+
|
17
|
+
@classmethod
|
18
|
+
def get(cls, key):
|
19
|
+
if not cls._instance:
|
20
|
+
cls._instance = ToolConfig()
|
21
|
+
return cls._instance.config.get(key)
|
22
|
+
|
23
|
+
class FunctionRegistry:
|
24
|
+
_tools = {}
|
25
|
+
|
26
|
+
@classmethod
|
27
|
+
def register(cls, tool_class):
|
28
|
+
cls._tools[tool_class().definition['function']['name']] = tool_class
|
29
|
+
return tool_class
|
30
|
+
|
31
|
+
@classmethod
|
32
|
+
def get_tools(cls):
|
33
|
+
return [cls._tools[name]().definition for name in cls._tools]
|
34
|
+
|
35
|
+
def setup_logging():
|
36
|
+
"""Configure logging for the gofannon package."""
|
37
|
+
logger = logging.getLogger('')
|
38
|
+
log_level = os.getenv('GOFANNON_LOG_LEVEL', 'WARNING').upper()
|
39
|
+
level = getattr(logging, log_level, logging.WARNING)
|
40
|
+
|
41
|
+
# Clear existing handlers if any
|
42
|
+
if logger.handlers:
|
43
|
+
for handler in logger.handlers:
|
44
|
+
logger.removeHandler(handler)
|
45
|
+
|
46
|
+
# Configure new handler
|
47
|
+
handler = logging.StreamHandler()
|
48
|
+
formatter = logging.Formatter(
|
49
|
+
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
50
|
+
)
|
51
|
+
handler.setFormatter(formatter)
|
52
|
+
logger.addHandler(handler)
|
53
|
+
|
54
|
+
logger.setLevel(level)
|
55
|
+
logger.propagate = False
|
56
|
+
|
57
|
+
# Initialize logging when config is imported
|
58
|
+
setup_logging()
|
@@ -0,0 +1,77 @@
|
|
1
|
+
|
2
|
+
import requests
|
3
|
+
import json
|
4
|
+
|
5
|
+
from..base import BaseTool
|
6
|
+
from ..config import FunctionRegistry
|
7
|
+
import logging
|
8
|
+
|
9
|
+
logger = logging.getLogger(__name__)
|
10
|
+
|
11
|
+
@FunctionRegistry.register
|
12
|
+
class CommitFile(BaseTool):
|
13
|
+
def __init__(self,
|
14
|
+
api_key=None,
|
15
|
+
name="commit_file",):
|
16
|
+
super().__init__()
|
17
|
+
self.api_key = api_key
|
18
|
+
self.name = name
|
19
|
+
self.API_SERVICE = 'github'
|
20
|
+
|
21
|
+
@property
|
22
|
+
def definition(self):
|
23
|
+
return {
|
24
|
+
"type": "function",
|
25
|
+
"function": {
|
26
|
+
"name": self.name,
|
27
|
+
"description": "Commit a file to a GitHub repository",
|
28
|
+
"parameters": {
|
29
|
+
"type": "object",
|
30
|
+
"properties": {
|
31
|
+
"repo_url": {
|
32
|
+
"type": "string",
|
33
|
+
"description": "The URL of the repository, e.g. https://github.com/The-AI-Alliance//gofannon"
|
34
|
+
},
|
35
|
+
"file_path": {
|
36
|
+
"type": "string",
|
37
|
+
"description": "The path of the file in the repository, e.g. example.txt"
|
38
|
+
},
|
39
|
+
"file_contents": {
|
40
|
+
"type": "string",
|
41
|
+
"description": "The contents of the file as a string"
|
42
|
+
},
|
43
|
+
"commit_message": {
|
44
|
+
"type": "string",
|
45
|
+
"description": "The commit message, e.g. 'Added example.txt'"
|
46
|
+
}
|
47
|
+
},
|
48
|
+
"required": ["repo_url", "file_path", "file_contents", "commit_message"]
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
def fn(self, repo_url,
|
54
|
+
file_path,
|
55
|
+
file_contents,
|
56
|
+
commit_message)-> str:
|
57
|
+
logger.debug(f"Committing file {file_path} to {repo_url}")
|
58
|
+
# Extracting the owner and repo name from the URL
|
59
|
+
repo_parts = repo_url.rstrip('/').split('/')
|
60
|
+
owner = repo_parts[-2]
|
61
|
+
repo = repo_parts[-1]
|
62
|
+
|
63
|
+
api_url = f"https://api.github.com/repos/{owner}/{repo}/contents/{file_path}"
|
64
|
+
headers = {
|
65
|
+
'Authorization': f'token {self.api_key}',
|
66
|
+
'Content-Type': 'application/json'
|
67
|
+
}
|
68
|
+
|
69
|
+
data = {
|
70
|
+
"message": commit_message,
|
71
|
+
"content": file_contents
|
72
|
+
}
|
73
|
+
|
74
|
+
response = requests.put(api_url, headers=headers, data=json.dumps(data))
|
75
|
+
response.raise_for_status()
|
76
|
+
|
77
|
+
return response.json()
|
@@ -0,0 +1,116 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
import requests
|
4
|
+
import json
|
5
|
+
import git
|
6
|
+
from pathlib import Path
|
7
|
+
|
8
|
+
from..base import BaseTool
|
9
|
+
from ..config import FunctionRegistry
|
10
|
+
import logging
|
11
|
+
|
12
|
+
logger = logging.getLogger(__name__)
|
13
|
+
|
14
|
+
@FunctionRegistry.register
|
15
|
+
class CommitFiles(BaseTool):
|
16
|
+
def __init__(self,
|
17
|
+
api_key=None,
|
18
|
+
name="commit_files",
|
19
|
+
git_user_name=None,
|
20
|
+
git_user_email=None):
|
21
|
+
super().__init__()
|
22
|
+
self.api_key = api_key
|
23
|
+
self.name = name
|
24
|
+
self.git_user_name = git_user_name
|
25
|
+
self.git_user_email = git_user_email
|
26
|
+
self.API_SERVICE = 'github'
|
27
|
+
|
28
|
+
|
29
|
+
@property
|
30
|
+
def definition(self):
|
31
|
+
return {
|
32
|
+
"type": "function",
|
33
|
+
"function": {
|
34
|
+
"name": self.name,
|
35
|
+
"description": "Commit multiple files to a GitHub repository",
|
36
|
+
"parameters": {
|
37
|
+
"type": "object",
|
38
|
+
"properties": {
|
39
|
+
"repo_url": {
|
40
|
+
"type": "string",
|
41
|
+
"description": "The URL of the repository, e.g. https://github.com/The-AI-Alliance//gofannon"
|
42
|
+
},
|
43
|
+
"branch": {
|
44
|
+
"type": "string",
|
45
|
+
"description": "The branch to commit to, e.g. 'main' or 'new-branch'"
|
46
|
+
},
|
47
|
+
"commit_msg": {
|
48
|
+
"type": "string",
|
49
|
+
"description": "The commit message, e.g. 'Added new files'"
|
50
|
+
},
|
51
|
+
"files_json": {
|
52
|
+
"type": "string",
|
53
|
+
"description": "A JSON string containing a list of files to commit, e.g. '{\"files\": [{\"path\": \"file1.py\", \"code\": \"import os\"}, {\"path\": \"file2.py\", \"code\": \"import sys\"}]}'"
|
54
|
+
},
|
55
|
+
"base_branch": {
|
56
|
+
"type": "string",
|
57
|
+
"description": "Optional. The base branch to create the new branch from. Default: 'main'"
|
58
|
+
}
|
59
|
+
},
|
60
|
+
"required": ["repo_url", "branch", "commit_msg", "files_json"]
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
def fn(self, repo_url, branch, commit_msg, files_json, base_branch='main'):
|
66
|
+
logger.debug(f"Committing files to {repo_url}")
|
67
|
+
# Extracting the owner and repo name from the URL
|
68
|
+
repo_parts = repo_url.rstrip('/').split('/')
|
69
|
+
owner = repo_parts[-2]
|
70
|
+
repo = repo_parts[-1]
|
71
|
+
|
72
|
+
if repo_url.startswith("https://"):
|
73
|
+
repo_url = repo_url.replace("https://", "https://"+ self.api_key+"@")
|
74
|
+
elif repo_url.startswith("github.com"):
|
75
|
+
repo_url = f"https://{self.api_key}@{repo_url}"
|
76
|
+
# Clone the repository
|
77
|
+
repo_dir = f"/tmp/{repo}"
|
78
|
+
|
79
|
+
|
80
|
+
if os.path.exists(repo_dir):
|
81
|
+
repo = git.Repo(repo_dir)
|
82
|
+
else:
|
83
|
+
repo = git.Repo.clone_from(repo_url, repo_dir)
|
84
|
+
repo.config_writer().set_value("user", "name", self.git_user_name).release()
|
85
|
+
repo.config_writer().set_value("user", "email", self.git_user_email).release()
|
86
|
+
|
87
|
+
# Check if the branch exists
|
88
|
+
if branch in repo.heads:
|
89
|
+
# If it does, checkout the branch and pull the latest changes
|
90
|
+
repo.git.checkout(branch)
|
91
|
+
repo.git.pull()
|
92
|
+
else:
|
93
|
+
# If it does not exist, checkout the base branch and create a new branch
|
94
|
+
try:
|
95
|
+
repo.git.checkout(base_branch)
|
96
|
+
except git.exc.GitCommandError:
|
97
|
+
# If the base branch does not exist, raise an error
|
98
|
+
raise ValueError(f"Base branch '{base_branch}' does not exist.")
|
99
|
+
repo.git.checkout('-b', branch)
|
100
|
+
|
101
|
+
# Load the JSON string
|
102
|
+
files = json.loads(files_json)['files']
|
103
|
+
# Update or create the files
|
104
|
+
for file in files:
|
105
|
+
file_path = file['path']
|
106
|
+
code = file['code']
|
107
|
+
with open(f"{repo_dir}/{file_path}", 'w') as f:
|
108
|
+
f.write(code)
|
109
|
+
repo.index.add(Path(file_path))
|
110
|
+
|
111
|
+
# Commit the files
|
112
|
+
repo.index.commit(commit_msg)
|
113
|
+
|
114
|
+
origin = repo.remotes.origin
|
115
|
+
origin.push(branch)
|
116
|
+
return "Files committed and pushed successfully"
|
@@ -0,0 +1,78 @@
|
|
1
|
+
from requests import post
|
2
|
+
from json import dumps
|
3
|
+
from..base import BaseTool
|
4
|
+
from ..config import FunctionRegistry
|
5
|
+
import logging
|
6
|
+
|
7
|
+
logger = logging.getLogger(__name__)
|
8
|
+
|
9
|
+
@FunctionRegistry.register
|
10
|
+
class CreateIssue(BaseTool):
|
11
|
+
def __init__(self,
|
12
|
+
api_key=None,
|
13
|
+
name="create_issue"):
|
14
|
+
super().__init__()
|
15
|
+
self.api_key = api_key
|
16
|
+
self.name = name
|
17
|
+
self.API_SERVICE = 'github'
|
18
|
+
|
19
|
+
@property
|
20
|
+
def definition(self):
|
21
|
+
return {
|
22
|
+
"type": "function",
|
23
|
+
"function": {
|
24
|
+
"name": self.name,
|
25
|
+
"description": "Create an issue in a GitHub repository",
|
26
|
+
"parameters": {
|
27
|
+
"type": "object",
|
28
|
+
"properties": {
|
29
|
+
"repo_url": {
|
30
|
+
"type": "string",
|
31
|
+
"description": "The URL of the repository, e.g. https://github.com/The-AI-Alliance//gofannon"
|
32
|
+
},
|
33
|
+
"title": {
|
34
|
+
"type": "string",
|
35
|
+
"description": "The title of the issue"
|
36
|
+
},
|
37
|
+
"body": {
|
38
|
+
"type": "string",
|
39
|
+
"description": "The body of the issue"
|
40
|
+
},
|
41
|
+
"labels": {
|
42
|
+
"type": "array",
|
43
|
+
"items": {
|
44
|
+
"type": "string"
|
45
|
+
},
|
46
|
+
"description": "An array of labels for the issue"
|
47
|
+
}
|
48
|
+
},
|
49
|
+
"required": ["repo_url", "title", "body"]
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
def fn(self, repo_url, title, body, labels=None):
|
55
|
+
logger.debug(f"Crating issue'{title}' in repo {repo_url}")
|
56
|
+
# Extracting the owner and repo name from the URL
|
57
|
+
repo_parts = repo_url.rstrip('/').split('/')
|
58
|
+
owner = repo_parts[-2]
|
59
|
+
repo = repo_parts[-1]
|
60
|
+
|
61
|
+
api_url = f"https://api.github.com/repos/{owner}/{repo}/issues"
|
62
|
+
headers = {
|
63
|
+
'Authorization': f'token {self.api_key}',
|
64
|
+
'Content-Type': 'application/json'
|
65
|
+
}
|
66
|
+
|
67
|
+
payload = {
|
68
|
+
"title": title,
|
69
|
+
"body": body
|
70
|
+
}
|
71
|
+
|
72
|
+
if labels:
|
73
|
+
payload["labels"] = labels
|
74
|
+
|
75
|
+
response = post(api_url, headers=headers, json=payload)
|
76
|
+
response.raise_for_status()
|
77
|
+
|
78
|
+
return dumps(response.json())
|
@@ -0,0 +1,98 @@
|
|
1
|
+
import requests
|
2
|
+
from ..base import BaseTool
|
3
|
+
from ..config import FunctionRegistry
|
4
|
+
import logging
|
5
|
+
|
6
|
+
logger = logging.getLogger(__name__)
|
7
|
+
|
8
|
+
@FunctionRegistry.register
|
9
|
+
class GetRepoContents(BaseTool):
|
10
|
+
|
11
|
+
def __init__(self,
|
12
|
+
api_key=None,
|
13
|
+
name="get_repo_contents",):
|
14
|
+
super().__init__()
|
15
|
+
self.api_key = api_key
|
16
|
+
self.name = name
|
17
|
+
self.API_SERVICE = 'github'
|
18
|
+
self.eoi = {'js' : 'javascript',
|
19
|
+
'jsx' : 'javascript',
|
20
|
+
'ts' : 'typescript',
|
21
|
+
'tsx' : 'typescript',
|
22
|
+
'py' : 'python',
|
23
|
+
'html' : 'html',
|
24
|
+
'css' : 'css',
|
25
|
+
'scss' : 'scss',
|
26
|
+
'sass' : 'sass',
|
27
|
+
'md' : 'markdown',
|
28
|
+
'json' : 'json'}
|
29
|
+
|
30
|
+
@property
|
31
|
+
def definition(self):
|
32
|
+
return {
|
33
|
+
"type": "function",
|
34
|
+
"function": {
|
35
|
+
"name": self.name,
|
36
|
+
"description": "Get contents of repo on github",
|
37
|
+
"parameters": {
|
38
|
+
"type": "object",
|
39
|
+
"properties": {
|
40
|
+
"repo_url": {
|
41
|
+
"type": "string",
|
42
|
+
"description":
|
43
|
+
"The URL of the Repo this is for reading an entire repo, not individual files., e.g. https://github.com/The-AI-Alliance//gofannon"
|
44
|
+
},
|
45
|
+
"directory_path": {
|
46
|
+
"type": "string",
|
47
|
+
"description": "Path from repository root of the directory of interest. Default '/'"
|
48
|
+
},
|
49
|
+
# "eoi": {
|
50
|
+
# "type": "dictionary",
|
51
|
+
# "description": "Extensions of interest. If not set, defaults to self.eoi (which contains common Python, Javascript, HTML, and Markdown extension). Example: `{'.js': 'javascript'}`",
|
52
|
+
# }
|
53
|
+
},
|
54
|
+
"required": ["repo_url"]
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
def fn(self, repo_url,
|
60
|
+
directory_path = "/",
|
61
|
+
eoi = None)-> str:
|
62
|
+
logger.debug(f"Getting contents of repo {repo_url}")
|
63
|
+
if eoi is None:
|
64
|
+
eoi = self.eoi
|
65
|
+
# Extracting the owner and repo name from the URL
|
66
|
+
repo_parts = repo_url.rstrip('/').split('/')
|
67
|
+
owner = repo_parts[-2]
|
68
|
+
repo = repo_parts[-1]
|
69
|
+
|
70
|
+
api_url = f"https://api.github.com/repos/{owner}/{repo}/contents/{directory_path}"
|
71
|
+
headers = {
|
72
|
+
'Authorization': f'token {self.api_key}'
|
73
|
+
}
|
74
|
+
|
75
|
+
response = requests.get(api_url, headers=headers)
|
76
|
+
response.raise_for_status()
|
77
|
+
|
78
|
+
contents = response.json()
|
79
|
+
|
80
|
+
result = []
|
81
|
+
|
82
|
+
for item in contents:
|
83
|
+
if item['type'] == 'file':
|
84
|
+
file_response = requests.get(item['download_url'], headers=headers)
|
85
|
+
extension = item['name'].split('.')[-1]
|
86
|
+
if extension in eoi:
|
87
|
+
language = eoi[extension]
|
88
|
+
else:
|
89
|
+
continue
|
90
|
+
file_response.raise_for_status()
|
91
|
+
file_content = file_response.text
|
92
|
+
result.append(f"{item['path']}\n```{language}\n{file_content}\n```")
|
93
|
+
elif item['type'] == 'dir':
|
94
|
+
# Recursively go through subdirectories
|
95
|
+
subdirectory_contents = self.fn(repo_url, item['path'], eoi)
|
96
|
+
result.append(subdirectory_contents)
|
97
|
+
|
98
|
+
return "\n\n".join(result)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
|
2
|
+
from..base import BaseTool
|
3
|
+
import requests
|
4
|
+
import json
|
5
|
+
from ..config import FunctionRegistry
|
6
|
+
import logging
|
7
|
+
|
8
|
+
logger = logging.getLogger(__name__)
|
9
|
+
|
10
|
+
@FunctionRegistry.register
|
11
|
+
class ReadIssue(BaseTool):
|
12
|
+
def __init__(self, api_key=None, name="read_issue"):
|
13
|
+
super().__init__()
|
14
|
+
self.api_key = api_key
|
15
|
+
self.name = name
|
16
|
+
self.API_SERVICE = 'github'
|
17
|
+
|
18
|
+
@property
|
19
|
+
def definition(self):
|
20
|
+
return {
|
21
|
+
"type": "function",
|
22
|
+
"function": {
|
23
|
+
"name": self.name,
|
24
|
+
"description": "Read an issue and its comments from a GitHub repository",
|
25
|
+
"parameters": {
|
26
|
+
"type": "object",
|
27
|
+
"properties": {
|
28
|
+
"repo_url": {
|
29
|
+
"type": "string",
|
30
|
+
"description": "The URL of the repository, e.g. https://github.com/The-AI-Alliance//gofannon"
|
31
|
+
},
|
32
|
+
"issue_number": {
|
33
|
+
"type": "integer",
|
34
|
+
"description": "The number of the issue to read"
|
35
|
+
}
|
36
|
+
},
|
37
|
+
"required": ["repo_url", "issue_number"]
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
def fn(self, repo_url, issue_number):
|
43
|
+
logger.debug(f"Reading issue number {issue_number} from repo {repo_url}")
|
44
|
+
# Extracting the owner and repo name from the URL
|
45
|
+
repo_parts = repo_url.rstrip('/').split('/')
|
46
|
+
owner = repo_parts[-2]
|
47
|
+
repo = repo_parts[-1]
|
48
|
+
|
49
|
+
issue_url = f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}"
|
50
|
+
comment_url = f"https://api.github.com/repos/{owner}/{repo}/issues/{issue_number}/comments"
|
51
|
+
|
52
|
+
headers = {
|
53
|
+
'Authorization': f'token {self.api_key}'
|
54
|
+
}
|
55
|
+
|
56
|
+
issue_response = requests.get(issue_url, headers=headers)
|
57
|
+
issue_response.raise_for_status()
|
58
|
+
|
59
|
+
comment_response = requests.get(comment_url, headers=headers)
|
60
|
+
comment_response.raise_for_status()
|
61
|
+
|
62
|
+
issue_data = issue_response.json()
|
63
|
+
comment_data = comment_response.json()
|
64
|
+
|
65
|
+
result = {
|
66
|
+
"issue": issue_data,
|
67
|
+
"comments": comment_data
|
68
|
+
}
|
69
|
+
|
70
|
+
return json.dumps(result, indent=4)
|
@@ -0,0 +1,67 @@
|
|
1
|
+
from..base import BaseTool
|
2
|
+
import requests
|
3
|
+
from ..config import FunctionRegistry
|
4
|
+
import logging
|
5
|
+
|
6
|
+
logger = logging.getLogger(__name__)
|
7
|
+
|
8
|
+
@FunctionRegistry.register
|
9
|
+
class SearchRepos(BaseTool):
|
10
|
+
def __init__(self,
|
11
|
+
api_key=None,
|
12
|
+
name="search_repos",):
|
13
|
+
super().__init__()
|
14
|
+
self.api_key = api_key
|
15
|
+
self.name = name
|
16
|
+
self.API_SERVICE = 'github'
|
17
|
+
|
18
|
+
@property
|
19
|
+
def definition(self):
|
20
|
+
return {
|
21
|
+
"type": "function",
|
22
|
+
"function": {
|
23
|
+
"name": self.name,
|
24
|
+
"description": "Search for GitHub repositories",
|
25
|
+
"parameters": {
|
26
|
+
"type": "object",
|
27
|
+
"properties": {
|
28
|
+
"query": {
|
29
|
+
"type": "string",
|
30
|
+
"description": "The search query, e.g. 'machine learning'"
|
31
|
+
},
|
32
|
+
"page": {
|
33
|
+
"type": "integer",
|
34
|
+
"description": "The page number to retrieve (default: 1)"
|
35
|
+
},
|
36
|
+
"per_page": {
|
37
|
+
"type": "integer",
|
38
|
+
"description": "The number of results per page (default: 10)"
|
39
|
+
}
|
40
|
+
},
|
41
|
+
"required": ["query"]
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
def fn(self, query, page=1, per_page=10) -> str:
|
47
|
+
logger.debug(f"Searching github.com for '{query}'")
|
48
|
+
api_url = f"https://api.github.com/search/repositories"
|
49
|
+
headers = {
|
50
|
+
'Authorization': f'token {self.api_key}'
|
51
|
+
}
|
52
|
+
params = {
|
53
|
+
"q": query,
|
54
|
+
"page": page,
|
55
|
+
"per_page": per_page
|
56
|
+
}
|
57
|
+
|
58
|
+
response = requests.get(api_url, headers=headers, params=params)
|
59
|
+
response.raise_for_status()
|
60
|
+
|
61
|
+
results = response.json()
|
62
|
+
|
63
|
+
formatted_results = []
|
64
|
+
for result in results['items']:
|
65
|
+
formatted_results.append(f"**{result['name']}** by **{result['owner']['login']}** - {result['description']}")
|
66
|
+
|
67
|
+
return "\n\n".join(formatted_results)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
from requests import get
|
2
|
+
from json import dumps
|
3
|
+
|
4
|
+
from ..base import BaseTool
|
5
|
+
from ..config import FunctionRegistry
|
6
|
+
import logging
|
7
|
+
|
8
|
+
logger = logging.getLogger(__name__)
|
9
|
+
|
10
|
+
@FunctionRegistry.register
|
11
|
+
class ComplaintsByVehicle(BaseTool):
|
12
|
+
def __init__(self,
|
13
|
+
api_key=None,
|
14
|
+
name="complaints_by_vehicle",):
|
15
|
+
super().__init__()
|
16
|
+
self.api_key = api_key
|
17
|
+
self.name = name
|
18
|
+
self.API_SERVICE = 'nhtsa'
|
19
|
+
|
20
|
+
@property
|
21
|
+
def definition(self):
|
22
|
+
return {
|
23
|
+
"type": "function",
|
24
|
+
"function": {
|
25
|
+
"name": self.name,
|
26
|
+
"description": "Get complaints by vehicle make, model, and year",
|
27
|
+
"parameters": {
|
28
|
+
"type": "object",
|
29
|
+
"properties": {
|
30
|
+
"make": {
|
31
|
+
"type": "string",
|
32
|
+
"description": "The make of the vehicle, e.g. Acura"
|
33
|
+
},
|
34
|
+
"model": {
|
35
|
+
"type": "string",
|
36
|
+
"description": "The model of the vehicle, e.g. ILX"
|
37
|
+
},
|
38
|
+
"modelYear": {
|
39
|
+
"type": "string",
|
40
|
+
"description": "The year of the vehicle, e.g. 2022"
|
41
|
+
}
|
42
|
+
},
|
43
|
+
"required": ["make", "model", "modelYear"]
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
def fn(self, make,
|
49
|
+
model,
|
50
|
+
modelYear)-> str:
|
51
|
+
logger.debug(f"Searching for complaints related to {modelYear} {make} {model}")
|
52
|
+
base_url = "https://api.nhtsa.gov/complaints/complaintsByVehicle"
|
53
|
+
payload = {
|
54
|
+
"make": make,
|
55
|
+
"model": model,
|
56
|
+
"modelYear": modelYear
|
57
|
+
}
|
58
|
+
r = get(base_url, params=payload)
|
59
|
+
return dumps(r.json())
|