Commit
Β·
0b10ccb
1
Parent(s):
4e10e1e
update app
Browse files
README.md
CHANGED
@@ -12,4 +12,86 @@ tags:
|
|
12 |
- tool
|
13 |
---
|
14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
12 |
- tool
|
13 |
---
|
14 |
|
15 |
+
# π Linkup Web Search Tool
|
16 |
+
|
17 |
+
The **Linkup Search Tool** is a [SmolAgents](https://github.com/huggingface/smolagents)βcompatible tool that allows agents to search the public and premium web in real-time using the [Linkup API](https://linkup.so).
|
18 |
+
|
19 |
+
Powered by advanced depth-aware search logic (`standard` vs `deep`), this tool is ideal for retrieving up-to-date insights, articles, and structured search summaries β all within your SmolAgents or Python workflows.
|
20 |
+
|
21 |
+
---
|
22 |
+
|
23 |
+
## π Features
|
24 |
+
|
25 |
+
- π **Web-wide, real-time search** via Linkup API
|
26 |
+
- π§ Supports **depth-aware querying** (`standard` or `deep`)
|
27 |
+
- π€ Compatible with `smolagents.CodeAgent` and manual usage
|
28 |
+
|
29 |
+
---
|
30 |
+
|
31 |
+
## π¦ Installation
|
32 |
+
|
33 |
+
```bash
|
34 |
+
pip install linkup-sdk smolagents
|
35 |
+
```
|
36 |
+
|
37 |
+
Youβll also need a [Linkup API key](https://linkup.so) to use the tool. You get $5 credits on signing up to try it out.
|
38 |
+
|
39 |
+
---
|
40 |
+
|
41 |
+
## π Setup API Key
|
42 |
+
|
43 |
+
You can provide the API key:
|
44 |
+
- At runtime
|
45 |
+
- Or by setting the environment variable:
|
46 |
+
|
47 |
+
```bash
|
48 |
+
export LINKUP_API_KEY="your-linkup-api-key"
|
49 |
+
```
|
50 |
+
|
51 |
+
You **must** however pass the `linkup_api_key` as a parameter in the space plug-and-play.
|
52 |
+
This ensures safe and personalized access to your Linkup account in public environments.
|
53 |
+
|
54 |
+
---
|
55 |
+
|
56 |
+
## π§ Usage with SmolAgents
|
57 |
+
|
58 |
+
```python
|
59 |
+
from smolagents import load_tool
|
60 |
+
|
61 |
+
tool = load_tool("Linkup-Platform/linkup-search-tool", trust_remote_code=True)
|
62 |
+
|
63 |
+
tool.forward(
|
64 |
+
query="What are the latest trends in generative AI?",
|
65 |
+
depth="deep",
|
66 |
+
)
|
67 |
+
```
|
68 |
+
---
|
69 |
+
|
70 |
+
## π― When to Use `standard` vs `deep`
|
71 |
+
|
72 |
+
| Mode | Best For |
|
73 |
+
|------------|-----------------------------------------------|
|
74 |
+
| `standard` | Quick factual lookups, direct answers |
|
75 |
+
| `deep` | Complex topics, analysis, multiple perspectives, latest news |
|
76 |
+
|
77 |
+
---
|
78 |
+
|
79 |
+
## π¬ Example Result (truncated)
|
80 |
+
|
81 |
+
```markdown
|
82 |
+
**Search Results:**
|
83 |
+
|
84 |
+
1. **The State of Generative AI 2024**
|
85 |
+
URL: https://venturebeat.com/generative-ai-2024
|
86 |
+
Generative AI is reshaping industries, with key players like OpenAI, Anthropic, and Google DeepMind...
|
87 |
+
|
88 |
+
2. **AI Trends: What's Coming Next?**
|
89 |
+
URL: https://techcrunch.com/ai-trends-2024
|
90 |
+
This year weβll see more foundation model APIs, compliance tooling, and multi-modal agents...
|
91 |
+
```
|
92 |
+
|
93 |
+
---
|
94 |
+
|
95 |
+
For questions or API access, visit [linkup.so](https://linkup.so).
|
96 |
+
|
97 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
app.py
CHANGED
@@ -1,39 +1,74 @@
|
|
1 |
import gradio as gr
|
2 |
-
from tool import LinkupSearchTool
|
3 |
|
4 |
def run_search(query, depth, api_key):
|
5 |
-
if not query or not depth or not api_key:
|
6 |
return "β All fields are required."
|
7 |
-
|
8 |
try:
|
9 |
-
|
10 |
-
tool = LinkupSearchTool(linkup_api_key=api_key) # Pass API key to constructor
|
11 |
return tool.forward(query=query, depth=depth)
|
12 |
except Exception as e:
|
13 |
return f"β Error: {str(e)}"
|
14 |
|
15 |
-
|
16 |
-
gr.
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
with gr.Row():
|
19 |
-
query_input = gr.Textbox(
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
fn=run_search,
|
28 |
inputs=[query_input, depth_input, api_key_input],
|
29 |
-
outputs=output
|
|
|
30 |
)
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
+
from tool import LinkupSearchTool
|
3 |
|
4 |
def run_search(query, depth, api_key):
|
5 |
+
if not query.strip() or not depth or not api_key.strip():
|
6 |
return "β All fields are required."
|
7 |
+
|
8 |
try:
|
9 |
+
tool = LinkupSearchTool(linkup_api_key=api_key)
|
|
|
10 |
return tool.forward(query=query, depth=depth)
|
11 |
except Exception as e:
|
12 |
return f"β Error: {str(e)}"
|
13 |
|
14 |
+
def enable_submit(q, d, k):
|
15 |
+
return gr.Button.update(interactive=bool(q.strip() and d and k.strip()))
|
16 |
+
|
17 |
+
with gr.Blocks(title="Linkup Web Search Tool") as demo:
|
18 |
+
gr.Markdown(
|
19 |
+
"""
|
20 |
+
# π Linkup Web Search Tool
|
21 |
+
Perform real-time web search using [Linkup API](https://linkup.so).
|
22 |
+
|
23 |
+
π§ Supports `standard` and `deep` query depth.
|
24 |
+
π Requires your personal Linkup API key.
|
25 |
+
π‘ Ideal for facts, trends, research, and real-time data discovery.
|
26 |
+
""",
|
27 |
+
elem_id="header",
|
28 |
+
)
|
29 |
+
|
30 |
with gr.Row():
|
31 |
+
query_input = gr.Textbox(
|
32 |
+
label="Search Query",
|
33 |
+
placeholder="e.g. AI trends in 2024",
|
34 |
+
lines=1,
|
35 |
+
)
|
36 |
+
depth_input = gr.Dropdown(
|
37 |
+
label="Search Depth",
|
38 |
+
choices=["standard", "deep"],
|
39 |
+
value="standard",
|
40 |
+
allow_custom_value=False,
|
41 |
+
)
|
42 |
+
api_key_input = gr.Textbox(
|
43 |
+
label="Linkup API Key",
|
44 |
+
placeholder="Paste your Linkup API key here",
|
45 |
+
type="password",
|
46 |
+
)
|
47 |
+
|
48 |
+
search_btn = gr.Button("π Search", interactive=False)
|
49 |
+
output = gr.Markdown("π¬ *Enter a query and click Search to begin.*", elem_id="output")
|
50 |
+
|
51 |
+
# Loading spinner and search button connection
|
52 |
+
search_btn.click(
|
53 |
fn=run_search,
|
54 |
inputs=[query_input, depth_input, api_key_input],
|
55 |
+
outputs=output,
|
56 |
+
show_progress=True,
|
57 |
)
|
58 |
+
|
59 |
+
# Dynamic form validation
|
60 |
+
query_input.input(enable_submit, [query_input, depth_input, api_key_input], [search_btn])
|
61 |
+
depth_input.input(enable_submit, [query_input, depth_input, api_key_input], [search_btn])
|
62 |
+
api_key_input.input(enable_submit, [query_input, depth_input, api_key_input], [search_btn])
|
63 |
+
|
64 |
+
# Footer
|
65 |
+
gr.Markdown(
|
66 |
+
"""
|
67 |
+
---
|
68 |
+
β
Built with [SmolAgents](https://github.com/huggingface/smolagents) + [Gradio](https://gradio.app)
|
69 |
+
π Powered by [Linkup](https://linkup.so)
|
70 |
+
""",
|
71 |
+
elem_id="footer",
|
72 |
+
)
|
73 |
+
|
74 |
+
demo.launch()
|
requirements.txt
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
-
linkup-sdk
|
2 |
smolagents
|
3 |
gradio
|
|
|
1 |
+
linkup-sdk==0.2.4
|
2 |
smolagents
|
3 |
gradio
|
tool.py
CHANGED
@@ -1,33 +1,37 @@
|
|
1 |
-
from typing import
|
|
|
2 |
from smolagents.tools import Tool
|
3 |
|
4 |
class LinkupSearchTool(Tool):
|
5 |
"""LinkupSearchTool tool.
|
6 |
|
7 |
-
LinkupSearchTool performs web search queries using the Linkup API, which includes results from both
|
8 |
-
public and premium web sources. It supports two modes of search depth β standard and deep β allowing
|
9 |
-
for flexible information retrieval depending on the complexity of the query.
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
-
|
12 |
-
|
13 |
|
14 |
-
|
|
|
15 |
|
16 |
-
|
17 |
-
export LINKUP_API_KEY="your-api-key"
|
18 |
|
19 |
-
|
20 |
-
|
|
|
|
|
|
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
)
|
26 |
-
agent.run(query="What was Microsoft's revenue last quarter and was it well perceived by the market?", depth="deep")
|
27 |
|
28 |
-
Args:
|
29 |
-
linkup_api_key (str | None): Optional. If not provided, LinkupClient will check the LINKUP_API_KEY env variable.
|
30 |
-
"""
|
31 |
name = "search_web"
|
32 |
description = "Performs an online search using Linkup search engine and retrieves the top results as a string. This function is useful for accessing real-time information, including news, articles, and other relevant web content."
|
33 |
output_type = "string"
|
@@ -40,7 +44,7 @@ Args:
|
|
40 |
"description": "The search depth to perform. Use 'standard' for straightforward queries with likely direct answers (e.g., facts, definitions, simple explanations). Use 'deep' for: 1) complex queries requiring comprehensive analysis or information synthesis, 2) queries containing uncommon terms, specialized jargon, or abbreviations that may need additional context, or 3) questions likely requiring up-to-date or specialized web search results to answer effectively.",
|
41 |
},
|
42 |
}
|
43 |
-
|
44 |
def __init__(self, linkup_api_key: str | None = None, **kwargs) -> None:
|
45 |
super().__init__()
|
46 |
try:
|
@@ -52,10 +56,7 @@ Args:
|
|
52 |
|
53 |
self.client = LinkupClient(api_key=linkup_api_key)
|
54 |
|
55 |
-
def forward(self, query: str, depth:
|
56 |
-
|
57 |
-
if depth not in ["standard", "deep"]:
|
58 |
-
raise ValueError("depth must be 'standard' or 'deep'")
|
59 |
|
60 |
try:
|
61 |
response = self.client.search(
|
|
|
1 |
+
from typing import Literal
|
2 |
+
|
3 |
from smolagents.tools import Tool
|
4 |
|
5 |
class LinkupSearchTool(Tool):
|
6 |
"""LinkupSearchTool tool.
|
7 |
|
8 |
+
LinkupSearchTool performs web search queries using the Linkup API, which includes results from both
|
9 |
+
public and premium web sources. It supports two modes of search depth β standard and deep β allowing
|
10 |
+
for flexible information retrieval depending on the complexity of the query.
|
11 |
+
|
12 |
+
Setup:
|
13 |
+
Make sure your Linkup API key is exported to the environment:
|
14 |
+
|
15 |
+
.. code-block:: bash
|
16 |
|
17 |
+
pip install linkup-sdk
|
18 |
+
export LINKUP_API_KEY="your-api-key"
|
19 |
|
20 |
+
Example:
|
21 |
+
from smolagents import load_tool, CodeAgent, InferenceClientModel
|
22 |
|
23 |
+
linkup_tool = load_tool("Linkup-Platform/linkup-search-tool", trust_remote_code=True)
|
|
|
24 |
|
25 |
+
agent = CodeAgent(
|
26 |
+
tools=[linkup_tool()],
|
27 |
+
model=InferenceClientModel(),
|
28 |
+
)
|
29 |
+
agent.run(query="What was Microsoft's revenue last quarter and was it well perceived by the market?", depth="deep")
|
30 |
|
31 |
+
Args:
|
32 |
+
linkup_api_key (str | None): Optional. If not provided, LinkupClient will check the LINKUP_API_KEY env variable.
|
33 |
+
"""
|
|
|
|
|
34 |
|
|
|
|
|
|
|
35 |
name = "search_web"
|
36 |
description = "Performs an online search using Linkup search engine and retrieves the top results as a string. This function is useful for accessing real-time information, including news, articles, and other relevant web content."
|
37 |
output_type = "string"
|
|
|
44 |
"description": "The search depth to perform. Use 'standard' for straightforward queries with likely direct answers (e.g., facts, definitions, simple explanations). Use 'deep' for: 1) complex queries requiring comprehensive analysis or information synthesis, 2) queries containing uncommon terms, specialized jargon, or abbreviations that may need additional context, or 3) questions likely requiring up-to-date or specialized web search results to answer effectively.",
|
45 |
},
|
46 |
}
|
47 |
+
|
48 |
def __init__(self, linkup_api_key: str | None = None, **kwargs) -> None:
|
49 |
super().__init__()
|
50 |
try:
|
|
|
56 |
|
57 |
self.client = LinkupClient(api_key=linkup_api_key)
|
58 |
|
59 |
+
def forward(self, query: str, depth: Literal["standard", "deep"]) -> str:
|
|
|
|
|
|
|
60 |
|
61 |
try:
|
62 |
response = self.client.search(
|