init
Browse files- .gitignore +171 -0
- .gradio/certificate.pem +31 -0
- app.py +202 -0
- extra_search_tools.py +215 -0
- history.json +1 -0
- requirements.txt +42 -0
.gitignore
ADDED
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Byte-compiled / optimized / DLL files
|
2 |
+
__pycache__/
|
3 |
+
*.py[cod]
|
4 |
+
*$py.class
|
5 |
+
|
6 |
+
# C extensions
|
7 |
+
*.so
|
8 |
+
|
9 |
+
# Distribution / packaging
|
10 |
+
.Python
|
11 |
+
build/
|
12 |
+
develop-eggs/
|
13 |
+
dist/
|
14 |
+
downloads/
|
15 |
+
eggs/
|
16 |
+
.eggs/
|
17 |
+
lib/
|
18 |
+
lib64/
|
19 |
+
parts/
|
20 |
+
sdist/
|
21 |
+
var/
|
22 |
+
wheels/
|
23 |
+
share/python-wheels/
|
24 |
+
*.egg-info/
|
25 |
+
.installed.cfg
|
26 |
+
*.egg
|
27 |
+
MANIFEST
|
28 |
+
|
29 |
+
# PyInstaller
|
30 |
+
# Usually these files are written by a python script from a template
|
31 |
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
32 |
+
*.manifest
|
33 |
+
*.spec
|
34 |
+
|
35 |
+
# Installer logs
|
36 |
+
pip-log.txt
|
37 |
+
pip-delete-this-directory.txt
|
38 |
+
|
39 |
+
# Unit test / coverage reports
|
40 |
+
htmlcov/
|
41 |
+
.tox/
|
42 |
+
.nox/
|
43 |
+
.coverage
|
44 |
+
.coverage.*
|
45 |
+
.cache
|
46 |
+
nosetests.xml
|
47 |
+
coverage.xml
|
48 |
+
*.cover
|
49 |
+
*.py,cover
|
50 |
+
.hypothesis/
|
51 |
+
.pytest_cache/
|
52 |
+
cover/
|
53 |
+
|
54 |
+
# Translations
|
55 |
+
*.mo
|
56 |
+
*.pot
|
57 |
+
|
58 |
+
# Django stuff:
|
59 |
+
*.log
|
60 |
+
local_settings.py
|
61 |
+
db.sqlite3
|
62 |
+
db.sqlite3-journal
|
63 |
+
|
64 |
+
# Flask stuff:
|
65 |
+
instance/
|
66 |
+
.webassets-cache
|
67 |
+
|
68 |
+
# Scrapy stuff:
|
69 |
+
.scrapy
|
70 |
+
|
71 |
+
# Sphinx documentation
|
72 |
+
docs/_build/
|
73 |
+
|
74 |
+
# PyBuilder
|
75 |
+
.pybuilder/
|
76 |
+
target/
|
77 |
+
|
78 |
+
# Jupyter Notebook
|
79 |
+
.ipynb_checkpoints
|
80 |
+
|
81 |
+
# IPython
|
82 |
+
profile_default/
|
83 |
+
ipython_config.py
|
84 |
+
|
85 |
+
# pyenv
|
86 |
+
# For a library or package, you might want to ignore these files since the code is
|
87 |
+
# intended to run in multiple environments; otherwise, check them in:
|
88 |
+
# .python-version
|
89 |
+
|
90 |
+
# pipenv
|
91 |
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
92 |
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
93 |
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
94 |
+
# install all needed dependencies.
|
95 |
+
#Pipfile.lock
|
96 |
+
|
97 |
+
# UV
|
98 |
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
99 |
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
100 |
+
# commonly ignored for libraries.
|
101 |
+
#uv.lock
|
102 |
+
|
103 |
+
# poetry
|
104 |
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
105 |
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
106 |
+
# commonly ignored for libraries.
|
107 |
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
108 |
+
#poetry.lock
|
109 |
+
|
110 |
+
# pdm
|
111 |
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
112 |
+
#pdm.lock
|
113 |
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
114 |
+
# in version control.
|
115 |
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
116 |
+
.pdm.toml
|
117 |
+
.pdm-python
|
118 |
+
.pdm-build/
|
119 |
+
|
120 |
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
121 |
+
__pypackages__/
|
122 |
+
|
123 |
+
# Celery stuff
|
124 |
+
celerybeat-schedule
|
125 |
+
celerybeat.pid
|
126 |
+
|
127 |
+
# SageMath parsed files
|
128 |
+
*.sage.py
|
129 |
+
|
130 |
+
# Environments
|
131 |
+
.env
|
132 |
+
.venv
|
133 |
+
env/
|
134 |
+
venv/
|
135 |
+
ENV/
|
136 |
+
env.bak/
|
137 |
+
venv.bak/
|
138 |
+
|
139 |
+
# Spyder project settings
|
140 |
+
.spyderproject
|
141 |
+
.spyproject
|
142 |
+
|
143 |
+
# Rope project settings
|
144 |
+
.ropeproject
|
145 |
+
|
146 |
+
# mkdocs documentation
|
147 |
+
/site
|
148 |
+
|
149 |
+
# mypy
|
150 |
+
.mypy_cache/
|
151 |
+
.dmypy.json
|
152 |
+
dmypy.json
|
153 |
+
|
154 |
+
# Pyre type checker
|
155 |
+
.pyre/
|
156 |
+
|
157 |
+
# pytype static type analyzer
|
158 |
+
.pytype/
|
159 |
+
|
160 |
+
# Cython debug symbols
|
161 |
+
cython_debug/
|
162 |
+
|
163 |
+
# PyCharm
|
164 |
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
165 |
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
166 |
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
167 |
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
168 |
+
#.idea/
|
169 |
+
|
170 |
+
# PyPI configuration file
|
171 |
+
.pypirc
|
.gradio/certificate.pem
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-----BEGIN CERTIFICATE-----
|
2 |
+
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
|
31 |
+
-----END CERTIFICATE-----
|
app.py
ADDED
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2024-2025 Akihito Miyazaki.
|
2 |
+
# This code is derived from the DuckDuckGoSearchTool class,
|
3 |
+
# originally part of the HuggingFace smolagents library.
|
4 |
+
# https://github.com/huggingface/smolagents
|
5 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6 |
+
# you may not use this file except in compliance with the License.
|
7 |
+
# You may obtain a copy of the License at
|
8 |
+
#
|
9 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10 |
+
#
|
11 |
+
# Unless required by applicable law or agreed to in writing, software
|
12 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 |
+
# See the License for the specific language governing permissions and
|
15 |
+
# limitations under the License.
|
16 |
+
|
17 |
+
|
18 |
+
import os
|
19 |
+
import threading
|
20 |
+
from typing import Optional
|
21 |
+
|
22 |
+
from dotenv import load_dotenv
|
23 |
+
import gradio as gr
|
24 |
+
from smolagents import (
|
25 |
+
CodeAgent,
|
26 |
+
LiteLLMModel,
|
27 |
+
DuckDuckGoSearchTool,
|
28 |
+
)
|
29 |
+
from smolagents.agent_types import AgentText, AgentImage, AgentAudio
|
30 |
+
from smolagents.gradio_ui import pull_messages_from_step, handle_agent_output_types
|
31 |
+
from huggingface_hub import InferenceClient
|
32 |
+
|
33 |
+
|
34 |
+
from extra_search_tools import (
|
35 |
+
PrioritySearchTool,
|
36 |
+
BraveSearchTool,
|
37 |
+
GoogleCustomSearchTool,
|
38 |
+
)
|
39 |
+
|
40 |
+
|
41 |
+
def hf_chat(api_key, model, text):
|
42 |
+
client = InferenceClient(api_key=api_key)
|
43 |
+
messages = [
|
44 |
+
{
|
45 |
+
"role": "user",
|
46 |
+
"content": text,
|
47 |
+
}
|
48 |
+
]
|
49 |
+
|
50 |
+
stream = client.chat.completions.create(
|
51 |
+
model=model, messages=messages, max_tokens=6000, stream=False
|
52 |
+
)
|
53 |
+
|
54 |
+
return stream.choices[0].message.content
|
55 |
+
|
56 |
+
|
57 |
+
load_dotenv(override=True)
|
58 |
+
# login(os.getenv("HF_TOKEN"))
|
59 |
+
|
60 |
+
append_answer_lock = threading.Lock()
|
61 |
+
|
62 |
+
# without below chat will duplicate
|
63 |
+
custom_role_conversions = {"tool-call": "assistant", "tool-response": "user"}
|
64 |
+
|
65 |
+
model = LiteLLMModel(
|
66 |
+
"groq/llama3-8b-8192",
|
67 |
+
api_base="https://api.groq.com/openai/v1",
|
68 |
+
max_completion_tokens=500,
|
69 |
+
api_key=os.getenv("GROQ_API_KEY"), # Groq API
|
70 |
+
)
|
71 |
+
|
72 |
+
search_tool = PrioritySearchTool(
|
73 |
+
[
|
74 |
+
DuckDuckGoSearchTool(),
|
75 |
+
GoogleCustomSearchTool("YOUR_ENGINE_KEY"),
|
76 |
+
BraveSearchTool(),
|
77 |
+
],
|
78 |
+
"history.json",
|
79 |
+
)
|
80 |
+
WEB_TOOLS = [search_tool]
|
81 |
+
|
82 |
+
max_steps = 1
|
83 |
+
|
84 |
+
|
85 |
+
# Agent creation in a factory function
|
86 |
+
def create_agent():
|
87 |
+
print("create agent")
|
88 |
+
"""Creates a fresh agent instance for each session"""
|
89 |
+
return CodeAgent(
|
90 |
+
model=model,
|
91 |
+
tools=WEB_TOOLS,
|
92 |
+
max_steps=max_steps,
|
93 |
+
verbosity_level=1,
|
94 |
+
)
|
95 |
+
|
96 |
+
|
97 |
+
def stream_to_gradio(
|
98 |
+
agent,
|
99 |
+
task: str,
|
100 |
+
reset_agent_memory: bool = False,
|
101 |
+
additional_args: Optional[dict] = None,
|
102 |
+
):
|
103 |
+
"""Runs an agent with the given task and streams the messages from the agent as gradio ChatMessages."""
|
104 |
+
steps = 0
|
105 |
+
for step_log in agent.run(
|
106 |
+
task, stream=True, reset=reset_agent_memory, additional_args=additional_args
|
107 |
+
):
|
108 |
+
# I dont know the reason but call more steps
|
109 |
+
steps += 1
|
110 |
+
if steps <= max_steps:
|
111 |
+
for message in pull_messages_from_step(
|
112 |
+
step_log,
|
113 |
+
):
|
114 |
+
yield message
|
115 |
+
|
116 |
+
final_answer = step_log # Last log is the run's final_answer
|
117 |
+
final_answer = handle_agent_output_types(final_answer)
|
118 |
+
# print(final_answer)
|
119 |
+
if isinstance(final_answer, AgentText):
|
120 |
+
yield gr.ChatMessage(
|
121 |
+
role="assistant",
|
122 |
+
content=f"**Final answer:**\n{final_answer.to_string()}",
|
123 |
+
)
|
124 |
+
elif isinstance(final_answer, AgentImage):
|
125 |
+
yield gr.ChatMessage(
|
126 |
+
role="assistant",
|
127 |
+
content={"path": final_answer.to_string(), "mime_type": "image/png"},
|
128 |
+
)
|
129 |
+
elif isinstance(final_answer, AgentAudio):
|
130 |
+
yield gr.ChatMessage(
|
131 |
+
role="assistant",
|
132 |
+
content={"path": final_answer.to_string(), "mime_type": "audio/wav"},
|
133 |
+
)
|
134 |
+
else:
|
135 |
+
yield gr.ChatMessage(
|
136 |
+
role="assistant", content=f"**Final answer:** {str(final_answer)}"
|
137 |
+
)
|
138 |
+
|
139 |
+
|
140 |
+
class GradioUI:
|
141 |
+
"""A one-line interface to launch your agent in Gradio"""
|
142 |
+
|
143 |
+
def __init__(self, file_upload_folder: str | None = None):
|
144 |
+
self.file_upload_folder = file_upload_folder
|
145 |
+
if self.file_upload_folder is not None:
|
146 |
+
if not os.path.exists(file_upload_folder):
|
147 |
+
os.mkdir(file_upload_folder)
|
148 |
+
|
149 |
+
def interact_with_agent(self, prompt, messages, session_state):
|
150 |
+
# Get or create session-specific agent
|
151 |
+
if "agent" not in session_state:
|
152 |
+
session_state["agent"] = create_agent()
|
153 |
+
|
154 |
+
messages.append(gr.ChatMessage(role="user", content=prompt))
|
155 |
+
yield messages
|
156 |
+
|
157 |
+
# Use session's agent instance
|
158 |
+
for msg in stream_to_gradio(
|
159 |
+
session_state["agent"], task=prompt, reset_agent_memory=False
|
160 |
+
):
|
161 |
+
messages.append(msg)
|
162 |
+
pass
|
163 |
+
yield messages
|
164 |
+
yield messages
|
165 |
+
|
166 |
+
def launch(self, **kwargs):
|
167 |
+
with gr.Blocks(theme="ocean", fill_height=True) as demo:
|
168 |
+
gr.Markdown("""# Smolagents - ExtraSearchtools!
|
169 |
+
- [Google Custom Search](https://developers.google.com/custom-search/v1/overview) tool
|
170 |
+
- [Brave Search](https://brave.com/search/api/) tool
|
171 |
+
- PrioritySearchTool - try duckduckgo fist and then use google
|
172 |
+
- PrioritySearchTool - json-save function
|
173 |
+
|
174 |
+
Built with [smolagents](https://github.com/huggingface/smolagents).This Demo only work duckduckgo if it's not rate-limited.Duplicate and set your own secret key
|
175 |
+
""")
|
176 |
+
# Add session state to store session-specific data
|
177 |
+
session_state = gr.State({}) # Initialize empty state for each session
|
178 |
+
|
179 |
+
chatbot = gr.Chatbot(
|
180 |
+
label="ExtraSearchtools",
|
181 |
+
type="messages",
|
182 |
+
avatar_images=(
|
183 |
+
None,
|
184 |
+
"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/smolagents/mascot_smol.png",
|
185 |
+
),
|
186 |
+
scale=1,
|
187 |
+
)
|
188 |
+
text_input = gr.Textbox(
|
189 |
+
lines=1, label="Your request", value="What is smolagents?"
|
190 |
+
)
|
191 |
+
text_input.submit(
|
192 |
+
self.interact_with_agent,
|
193 |
+
# Include session_state in function calls
|
194 |
+
[text_input, chatbot, gr.State({})],
|
195 |
+
[chatbot],
|
196 |
+
)
|
197 |
+
|
198 |
+
demo.launch(debug=True, share=True, **kwargs)
|
199 |
+
|
200 |
+
|
201 |
+
if __name__ == "__main__":
|
202 |
+
GradioUI().launch() # not support auto update restart by yourself :AttributeError: module '__main__' has no attribute 'demo'
|
extra_search_tools.py
ADDED
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2024-2025 Akihito Miyazaki.
|
2 |
+
# This code is derived from the DuckDuckGoSearchTool class,
|
3 |
+
# originally part of the HuggingFace smolagents library.
|
4 |
+
# https://github.com/huggingface/smolagents
|
5 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6 |
+
# you may not use this file except in compliance with the License.
|
7 |
+
# You may obtain a copy of the License at
|
8 |
+
#
|
9 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10 |
+
#
|
11 |
+
# Unless required by applicable law or agreed to in writing, software
|
12 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 |
+
# See the License for the specific language governing permissions and
|
15 |
+
# limitations under the License.
|
16 |
+
|
17 |
+
from smolagents import Tool
|
18 |
+
import json
|
19 |
+
import os
|
20 |
+
from datetime import datetime
|
21 |
+
|
22 |
+
"""This module provides search tools. The tools share a common name
|
23 |
+
because they are designed to be mutually exclusive (only one is used per query).
|
24 |
+
|
25 |
+
This code is derived from the DuckDuckGoSearchTool class in the HuggingFace
|
26 |
+
smolagents library.
|
27 |
+
|
28 |
+
TODO:
|
29 |
+
GoogleCustomSearchTool and BraveSearchTool are not using kwarg in init.
|
30 |
+
|
31 |
+
requires:
|
32 |
+
google-api-python-client
|
33 |
+
brave-search
|
34 |
+
"""
|
35 |
+
|
36 |
+
|
37 |
+
class PrioritySearchTool(Tool):
|
38 |
+
"""A tool that executes searches using multiple search tools in a prioritized order.
|
39 |
+
|
40 |
+
This tool takes a list of search tools and executes a query using them. It returns
|
41 |
+
the first successful result. Results are optionally cached and saved to a JSON file.
|
42 |
+
|
43 |
+
Attributes:
|
44 |
+
name (str): The name of the tool.
|
45 |
+
description (str): A description of the tool.
|
46 |
+
inputs (dict): The input schema for the tool.
|
47 |
+
output_type (str): The output type of the tool.
|
48 |
+
search_tools (list[Tool]): A list of search tools to use for searching.
|
49 |
+
save_json_path (str, optional): The path to a JSON file where search results
|
50 |
+
will be saved. Defaults to None.
|
51 |
+
history_results (dict): A dictionary storing past search results.
|
52 |
+
|
53 |
+
"""
|
54 |
+
|
55 |
+
name = "web_search"
|
56 |
+
description = """Performs a google-custom web search based on your query (think a Google search) then returns the top search results."""
|
57 |
+
inputs = {
|
58 |
+
"query": {"type": "string", "description": "The search query to perform."}
|
59 |
+
}
|
60 |
+
output_type = "string"
|
61 |
+
|
62 |
+
def __init__(
|
63 |
+
self,
|
64 |
+
search_tools: list[Tool],
|
65 |
+
save_json_path: str = None,
|
66 |
+
**kwargs,
|
67 |
+
):
|
68 |
+
super().__init__()
|
69 |
+
self.search_tools = search_tools
|
70 |
+
self.save_json_path = save_json_path
|
71 |
+
self.history_results = {}
|
72 |
+
|
73 |
+
def forward(self, query: str) -> str:
|
74 |
+
if os.path.exists(self.save_json_path):
|
75 |
+
with open(self.save_json_path, "r") as file:
|
76 |
+
self.history_results = json.load(file)
|
77 |
+
if query in self.history_results:
|
78 |
+
return self.history_results[query]["data"]
|
79 |
+
|
80 |
+
for search_tool in self.search_tools:
|
81 |
+
try:
|
82 |
+
result = search_tool(query=query)
|
83 |
+
if self.save_json_path:
|
84 |
+
class_name = search_tool.__class__.__name__
|
85 |
+
self.history_results[query] = {
|
86 |
+
"cdate": str(datetime.now()),
|
87 |
+
"name": class_name,
|
88 |
+
"data": result,
|
89 |
+
}
|
90 |
+
with open(self.save_json_path, "w") as file:
|
91 |
+
json.dump(self.history_results, file)
|
92 |
+
return result
|
93 |
+
|
94 |
+
except Exception as e:
|
95 |
+
print(f"{e}")
|
96 |
+
raise Exception("All search tools failed.")
|
97 |
+
|
98 |
+
|
99 |
+
class GoogleCustomSearchTool(Tool):
|
100 |
+
"""
|
101 |
+
use
|
102 |
+
https://github.com/googleapis/google-api-python-client/
|
103 |
+
|
104 |
+
parameter
|
105 |
+
https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list
|
106 |
+
|
107 |
+
Exp:another language
|
108 |
+
search = GoogleCustomSearchTool("33ec073e195bc4fcf", cr="countryJP", lr="lang_ja")
|
109 |
+
"""
|
110 |
+
|
111 |
+
name = "web_search"
|
112 |
+
description = """Performs a google-custom web search based on your query (think a Google search) then returns the top search results."""
|
113 |
+
inputs = {
|
114 |
+
"query": {"type": "string", "description": "The search query to perform."}
|
115 |
+
}
|
116 |
+
output_type = "string"
|
117 |
+
|
118 |
+
def __init__(self, cx, max_results=10, **kwargs):
|
119 |
+
super().__init__()
|
120 |
+
if cx is None:
|
121 |
+
raise ValueError(
|
122 |
+
"Need CX(Search Engine ID) need create in custom-search controlpanel"
|
123 |
+
)
|
124 |
+
self.cx = cx
|
125 |
+
self.max_results = max_results
|
126 |
+
api_key_env_name = "GOOGLE_CUSTOM_SEARCH_KEY"
|
127 |
+
self.kwargs = kwargs
|
128 |
+
try:
|
129 |
+
from googleapiclient.discovery import build
|
130 |
+
except ImportError as e:
|
131 |
+
raise ImportError(
|
132 |
+
"You must install package `google-api-python-client` to run this tool: for instance run `pip install google-api-python-client`."
|
133 |
+
) from e
|
134 |
+
import os
|
135 |
+
|
136 |
+
self.key = os.getenv(api_key_env_name)
|
137 |
+
|
138 |
+
self.custom_search = build("customsearch", "v1")
|
139 |
+
|
140 |
+
def forward(self, query: str) -> str:
|
141 |
+
results = (
|
142 |
+
self.custom_search.cse()
|
143 |
+
.list(
|
144 |
+
key=self.key, q=query, cx=self.cx, num=self.max_results, **self.kwargs
|
145 |
+
)
|
146 |
+
.execute()
|
147 |
+
)
|
148 |
+
|
149 |
+
results = results["items"]
|
150 |
+
|
151 |
+
if len(results) == 0:
|
152 |
+
raise Exception("No results found! Try a less restrictive/shorter query.")
|
153 |
+
postprocessed_results = [
|
154 |
+
f"[{result['title']}]({result['link']})\n{result['snippet']}"
|
155 |
+
for result in results
|
156 |
+
]
|
157 |
+
return "## Search Results\n\n" + "\n\n".join(postprocessed_results)
|
158 |
+
|
159 |
+
|
160 |
+
from smolagents import Tool
|
161 |
+
import json
|
162 |
+
|
163 |
+
|
164 |
+
class BraveSearchTool(Tool):
|
165 |
+
"""
|
166 |
+
Use
|
167 |
+
https://github.com/kayvane1/brave-api
|
168 |
+
|
169 |
+
query parameter
|
170 |
+
https://api-dashboard.search.brave.com/app/documentation/web-search/query
|
171 |
+
|
172 |
+
Exp:another language
|
173 |
+
search = BraveSearchTool(country="JP", search_lang="jp")
|
174 |
+
"""
|
175 |
+
|
176 |
+
name = "web_search"
|
177 |
+
description = """Performs a google-custom web search based on your query (think a Google search) then returns the top search results."""
|
178 |
+
inputs = {
|
179 |
+
"query": {"type": "string", "description": "The search query to perform."}
|
180 |
+
}
|
181 |
+
output_type = "string"
|
182 |
+
|
183 |
+
def __init__(self, max_results=10, **kwargs):
|
184 |
+
super().__init__()
|
185 |
+
self.max_results = max_results
|
186 |
+
api_key_env_name = "BRAVE_SEARCH_KEY"
|
187 |
+
self.kwargs = kwargs
|
188 |
+
try:
|
189 |
+
from brave import Brave
|
190 |
+
except ImportError as e:
|
191 |
+
raise ImportError(
|
192 |
+
# there are another lib.but this one work one python-3.10
|
193 |
+
"You must install package `brave-search` to run this tool: for instance run `pip install pip install brave-search`."
|
194 |
+
) from e
|
195 |
+
import os
|
196 |
+
|
197 |
+
self.brave = Brave(api_key=os.getenv(api_key_env_name))
|
198 |
+
|
199 |
+
def clean(text):
|
200 |
+
return text.replace("<STRING>", "").replace("</STRONG>")
|
201 |
+
|
202 |
+
def forward(self, query: str) -> str:
|
203 |
+
search_results = self.brave.search(
|
204 |
+
q=query, count=self.max_results, **self.kwargs
|
205 |
+
)
|
206 |
+
# pprint.pprint(search_results, indent=4)
|
207 |
+
results = search_results.web_results
|
208 |
+
# pprint.pprint(search_results.web_results, indent=4)
|
209 |
+
if len(results) == 0:
|
210 |
+
raise Exception("No results found! Try a less restrictive/shorter query.")
|
211 |
+
postprocessed_results = [
|
212 |
+
f"[{result['title']}]({result['url']._url})\n{self.clean(result['description'])}"
|
213 |
+
for result in results
|
214 |
+
]
|
215 |
+
return "## Search Results\n\n" + "\n\n".join(postprocessed_results)
|
history.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{"smolagents": {"cdate": "2025-03-14 16:04:17.000743", "name": "DuckDuckGoSearchTool", "data": "## Search Results\n\n[smolagents: a barebones library for agents. Agents write ... - GitHub](https://github.com/huggingface/smolagents)\nsmolagents is a library that enables you to run powerful agents in a few lines of code. It supports CodeAgents that write actions as Python code snippets, and integrates with various tools and models from Hugging Face Hub and other providers.\n\n[smolagents - Hugging Face](https://huggingface.co/docs/smolagents/index)\nsmolagents is a library that lets you create powerful agents with any LLM, including Code Agents. Learn how to use it with guides, tutorials and examples on the Hugging Face documentation.\n\n[Smolagents : Huggingface AI Agent Framework](https://smolagents.org/)\nSmolagents is a minimalist and efficient framework for creating and running AI agents with large language models. Learn how to use code agents, tools, and the Hugging Face Hub to build powerful and versatile agents for various tasks.\n\n[Agents - Guided tour - Smolagents](https://smolagents.org/docs/agents-guided-tour/)\nSmolagents lets you create agents that can use text-generation models and tools to solve tasks. Learn how to initialize, run, and customize agents with different models, tools, and options.\n\n[Building good Smolagents - Smolagents](https://smolagents.org/docs/building-good-smolagents/)\nSmolagents is a framework for creating agents that can perform tasks using natural language and external tools. Learn best practices for simplifying workflows, improving information flow, and debugging agents with LLMs.\n\n[Introducing smolagents , a simple library to build agents - Hugging Face](https://huggingface.co/blog/smolagents)\nsmolagents is a simple library that unlocks agentic capabilities for language models. It allows LLMs to write actions in code, such as calling external tools or executing loops, to solve real-world tasks.\n\n[Introduction to Agents - Hugging Face](https://huggingface.co/docs/smolagents/conceptual_guides/intro_agents)\nsmolagents documentation Introduction to Agents. smolagents Search documentation. Get started. \ud83e\udd17 Agents Guided tour. Tutorials. Building good agents \ud83d\udcca Inspect your agent runs using telemetry \ud83d\udee0\ufe0f Tools - in-depth guide \ud83d\udee1\ufe0f Secure code execution \ud83d\udcda Manage your agent's memory. Conceptual guides ...\n\n[smolagents/README.md at main \u00b7 huggingface/smolagents - GitHub](https://github.com/huggingface/smolagents/blob/main/README.md)\nsmolagents is a Python library that lets you create agents that can perform tasks using natural language and various tools. It supports code agents, model-agnostic agents, modality-agnostic agents, and tool-agnostic agents.\n\n[smolagents \u00b7 PyPI](https://pypi.org/project/smolagents/)\nsmolagents is a library that enables you to run powerful agents in a few lines of code. It offers: Simplicity: the logic for agents fits in ~1,000 lines of code (see agents.py).We kept abstractions to their minimal shape above raw code! \ud83e\uddd1\u200d\ud83d\udcbb First-class support for Code Agents.Our CodeAgent writes its actions in code (as opposed to \"agents being used to write code\").\n\n[SmolAgents. SmolAgents from HuggingFace | by Cobus Greyling | Feb, 2025 ...](https://cobusgreyling.medium.com/smolagents-7a4bf7712814)\nHugging Face launched SmolAgents with a clear mission: to democratise the creation of sophisticated agentic systems by prioritising simplicity and reducing technical overhead.. Unlike more complex frameworks, which often involve intricate architectures, SmolAgents intentionally strips away unnecessary layers of abstraction. The library emphasises lightweight efficiency without sacrificing ..."}, "What is smolagents?": {"cdate": "2025-03-14 18:08:58.593568", "name": "DuckDuckGoSearchTool", "data": "## Search Results\n\n[smolagents - Hugging Face](https://huggingface.co/docs/smolagents/index)\nsmolagents. This library is the simplest framework out there to build powerful agents! By the way, wtf are \"agents\"? We provide our definition in this page, where you'll also find tips for when to use them or not (spoilers: you'll often be better off without agents).\n\n[Smolagents : Huggingface AI Agent Framework](https://smolagents.org/)\n\ud83e\udd17 Smolagents is a minimalist AI agent framework developed by the Hugging Face team, crafted to enable developers to deploy robust agents with just a few lines of code. Embracing simplicity and efficiency, smolagents empowers large language models (LLMs) to interact seamlessly with the real world.\n\n[Introducing smolagents , a simple library to build agents - Hugging Face](https://huggingface.co/blog/smolagents)\nsmolagents is the successor to transformers.agents, and will be replacing it as transformers.agents gets deprecated in the future. Building an agent To build an agent, you need at least two elements: tools: a list of tools the agent has access to;\n\n[smolagents: a barebones library for agents. Agents write ... - GitHub](https://github.com/huggingface/smolagents)\nsmolagents is a library that enables you to run powerful agents in a few lines of code. It offers: Simplicity: the logic for agents fits in ~1,000 lines of code (see agents.py).We kept abstractions to their minimal shape above raw code! \ud83e\uddd1\u200d\ud83d\udcbb First-class support for Code Agents.Our CodeAgent writes its actions in code (as opposed to \"agents being used to write code\").\n\n[What are SmolAgents?: A Easy Guide With Code Examples](https://analyticsiksha.com/smolagents-by-hugging-face-a-comprehensive-guide/)\nIn the evolving world of artificial intelligence, Hugging Face has once again pushed the boundaries of innovation with its latest release: SmolAgents. SmolAgents - This lightweight, efficient, and versatile framework for building and running AI agents is designed to simplify complex workflows, making AI-powered solutions more accessible than ...\n\n[SmolAgents by Hugging Face: Build AI Agents in Under 30 Lines](https://www.analyticsvidhya.com/blog/2025/01/smolagents/)\nSmolAgents is an innovative library designed to simplify the creation and execution of powerful agents. Developed by Hugging Face, it stands out for its minimalist approach, with the entire agent logic encapsulated in approximately 1,000 lines of code. This streamlined design ensures ease of use while maintaining robust functionality.\n\n[Agents - Guided tour - Smolagents](https://smolagents.org/docs/agents-guided-tour/)\nfrom smolagents import tool @tool def model_download_tool(task: str) -> str: \"\"\" This is a tool that returns the most downloaded model of a given task on the Hugging Face Hub. It returns the name of the checkpoint.\n\n[HuggingFace smolagents: The best Multi-Agent framework so far?](https://medium.com/data-science-in-your-pocket/huggingface-smolagents-the-best-multi-agent-framework-so-far-313178ef3c2e)\nWhat are smolagents? Smolagents is a newly launched agent framework by Hugging Face, designed to simplify the creation of intelligent agents that leverage large language models (LLMs).\n\n[smolagents\u2014Simplifying AI Agent Development](https://smolagents.org/smolagents-simplifying-ai-agent-development/)\nWhat is smolagents? smolagents is an open-source, lightweight AI agent library that allows developers to create powerful agents with minimal code. With a core codebase of approximately 1,000 lines in agents.py, smolagents reduces unnecessary abstractions, making the development process straightforward and accessible.By focusing on simplicity and efficiency, smolagents enables LLMs to interact ...\n\n[Getting Started with Smolagents](https://debuggercafe.com/smolagents/)\nWe have three Python files: app.py, tool.py, tool_config.py. The primary code resides in the tool.py file. This contains a class to generate the image and is a subclass of the Tool class.. The app.py file just imports the class and launches the Gradio demo.. And finally, the tool_config.py file is what tells the load_tool function that this is a tool and how to use it."}}
|
requirements.txt
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
smolagents==1.9.1
|
2 |
+
anthropic>=0.37.1
|
3 |
+
beautifulsoup4>=4.12.3
|
4 |
+
datasets>=2.21.0
|
5 |
+
google_search_results>=2.4.2
|
6 |
+
huggingface_hub>=0.23.4
|
7 |
+
mammoth>=1.8.0
|
8 |
+
markdownify>=0.13.1
|
9 |
+
numexpr>=2.10.1
|
10 |
+
numpy>=2.1.2
|
11 |
+
openai>=1.52.2
|
12 |
+
openpyxl
|
13 |
+
pandas>=2.2.3
|
14 |
+
pathvalidate>=3.2.1
|
15 |
+
pdfminer>=20191125
|
16 |
+
pdfminer.six>=20240706
|
17 |
+
Pillow>=11.0.0
|
18 |
+
puremagic>=1.28
|
19 |
+
pypdf>=5.1.0
|
20 |
+
python-dotenv>=1.0.1
|
21 |
+
python_pptx>=1.0.2
|
22 |
+
Requests>=2.32.3
|
23 |
+
serpapi>=0.1.5
|
24 |
+
tqdm>=4.66.4
|
25 |
+
torch>=2.2.2
|
26 |
+
torchvision>=0.17.2
|
27 |
+
transformers>=4.46.0
|
28 |
+
youtube_transcript_api>=0.6.2
|
29 |
+
chess
|
30 |
+
sympy
|
31 |
+
pubchempy
|
32 |
+
Bio
|
33 |
+
scikit-learn
|
34 |
+
scipy
|
35 |
+
pydub
|
36 |
+
PyPDF2
|
37 |
+
python-pptx
|
38 |
+
torch
|
39 |
+
xlrd
|
40 |
+
SpeechRecognition
|
41 |
+
litellm
|
42 |
+
duckduckgo-search
|