LeoWalker commited on
Commit
e40e203
2 Parent(s): 00caf10 c7aea9b

Merge pull request #3 from leowalker89/EnableBraveSearchAI

Browse files
Files changed (6) hide show
  1. app.py +159 -88
  2. brave_ai.py +89 -0
  3. helpers.py +20 -67
  4. provider_info.py +18 -0
  5. requirements.txt +92 -6
  6. test_func.py +36 -0
app.py CHANGED
@@ -1,20 +1,32 @@
1
  import streamlit as st
2
  import random
3
- from helpers import query_you_com, query_tavily, query_perplexity
4
- from mongod_db import MongoDBHandler
5
- from swarms.utils.loguru_logger import logger
 
6
  import time
7
 
8
- mongo = MongoDBHandler()
9
 
10
  # Set Streamlit to wide mode
11
  st.set_page_config(layout="wide")
12
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  # Define the function to process the question
15
  def ProcessQuestion(question):
16
- # Randomly select two out of the three functions
17
- functions = [query_you_com, query_tavily, query_perplexity]
18
  selected_functions = random.sample(functions, 2)
19
 
20
  # Get answers from the selected functions
@@ -22,98 +34,157 @@ def ProcessQuestion(question):
22
  answer_b = selected_functions[1](question)
23
 
24
  # Log into mongodb
25
- try:
26
- logger.info(f"Logging question: {question}")
27
- mongo.add(
28
- {
29
- "question": question,
30
- "answer_a": answer_a,
31
- "answer_b": answer_b,
32
- "selected_functions": [f.__name__ for f in selected_functions],
33
- "query_time": time.time(),
34
- }
35
- )
36
- logger.info("Successfully logged into mongodb")
37
- except Exception as e:
38
- logger.error(f"Error logging into mongodb: {e}")
39
-
40
- return answer_a, answer_b
41
 
42
 
43
  # Initialize session state if not already done
44
- if "results_displayed" not in st.session_state:
45
- st.session_state["results_displayed"] = False
46
- if "answer_a" not in st.session_state:
47
- st.session_state["answer_a"] = ""
48
- if "answer_b" not in st.session_state:
49
- st.session_state["answer_b"] = ""
50
- if "question" not in st.session_state:
51
- st.session_state["question"] = ""
 
 
 
 
 
 
52
 
53
  # Streamlit app layout
54
  st.title("Search Engine Agent Comparison")
55
 
56
- # Create columns for the input and model selection
57
- input_col, control_col = st.columns([4, 1])
58
-
59
- with input_col:
60
- # Text box for user input with character limit
61
- question = st.text_area(
62
- "Enter your question here (max 1000 characters):", max_chars=1000
63
- )
64
-
65
- with control_col:
66
- # Submit button
67
- submit_button = st.button("Submit")
68
-
69
- if submit_button:
70
  if question:
71
- if len(question) <= 1000:
72
- # Process the question and get answers
73
- answer_a, answer_b = ProcessQuestion(question)
74
-
75
- # Save answers and state to session state
76
- st.session_state["answer_a"] = answer_a
77
- st.session_state["answer_b"] = answer_b
78
- st.session_state["question"] = question
79
- st.session_state["results_displayed"] = True
80
- else:
81
- st.error(
82
- "Your question exceeds the 1,000 character limit. Please shorten your question."
83
- )
84
- else:
85
- st.error("Please enter a question.")
86
-
87
- # Display results if available in session state
88
- if st.session_state["results_displayed"]:
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  col1, col2 = st.columns(2)
90
  with col1:
91
- st.write("### Output A")
92
  st.write(st.session_state["answer_a"])
93
- a_feedback_grid = st.columns(1)
94
  with col2:
95
- st.write("### Output B")
96
  st.write(st.session_state["answer_b"])
97
- b_feedback_grid = st.columns(2)
98
-
99
- # Create a placeholder for the feedback div
100
- feedback_placeholder = st.empty()
101
-
102
- def display_feedback(message):
103
- feedback_placeholder.markdown(
104
- f'<div style="position: fixed; bottom: 10px; left: 10px; background-color: #f0f0f0; padding: 10px; border-radius: 5px;">{message}</div>',
105
- unsafe_allow_html=True,
106
- )
107
-
108
- with a_feedback_grid[0]:
109
- if st.button("A is better 🥇"):
110
- display_feedback("You selected: A is better")
111
- with b_feedback_grid[0]:
112
- if st.button("B is better 💪"):
113
- display_feedback("You selected: B is better")
114
- with a_feedback_grid[0]:
115
- if st.button("It's a Tie 🤝"):
116
- display_feedback("You selected: It's a Tie")
117
- with b_feedback_grid[0]:
118
- if st.button("Both are bad 👎"):
119
- display_feedback("You selected: Both are bad")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
  import random
3
+ from helpers import query_you_com, query_tavily, query_perplexity, query_brave
4
+ from provider_info import search_providers
5
+ # from mongod_db import MongoDBHandler
6
+ # from swarms.utils.loguru_logger import logger
7
  import time
8
 
9
+ # mongo = MongoDBHandler()
10
 
11
  # Set Streamlit to wide mode
12
  st.set_page_config(layout="wide")
13
 
14
+ # Add information to sidebar
15
+ st.sidebar.title("About the App")
16
+ st.sidebar.write("""
17
+ This app allows you to compare responses from different search engines.
18
+ Submit a question, and you'll receive answers from two randomly selected search engines.
19
+ You can then vote on which response you prefer.
20
+ """)
21
+ st.sidebar.write("""
22
+ **[GitHub](https://github.com/leowalker89/SearchArena)**
23
+
24
+ """)
25
 
26
  # Define the function to process the question
27
  def ProcessQuestion(question):
28
+ # Randomly select two out of the four functions
29
+ functions = [query_you_com, query_tavily, query_perplexity, query_brave]
30
  selected_functions = random.sample(functions, 2)
31
 
32
  # Get answers from the selected functions
 
34
  answer_b = selected_functions[1](question)
35
 
36
  # Log into mongodb
37
+ # try:
38
+ # logger.info(f"Logging question: {question}")
39
+ # mongo.add(
40
+ # {
41
+ # "question": question,
42
+ # "answer_a": answer_a,
43
+ # "answer_b": answer_b,
44
+ # "selected_functions": [f.__name__ for f in selected_functions],
45
+ # "query_time": time.time(),
46
+ # }
47
+ # )
48
+ # logger.info("Successfully logged into mongodb")
49
+ # except Exception as e:
50
+ # logger.error(f"Error logging into mongodb: {e}")
51
+
52
+ return answer_a, answer_b, selected_functions
53
 
54
 
55
  # Initialize session state if not already done
56
+ default_values = {
57
+ "state": "arena_ready",
58
+ "question": "",
59
+ "answer_a": "",
60
+ "answer_b": "",
61
+ "source_a": "",
62
+ "source_b": "",
63
+ "winner": "",
64
+ "selected_button": ""
65
+ }
66
+
67
+ for key, value in default_values.items():
68
+ if key not in st.session_state:
69
+ st.session_state[key] = value
70
 
71
  # Streamlit app layout
72
  st.title("Search Engine Agent Comparison")
73
 
74
+ def on_submit():
75
+ question = st.session_state["question_input"]
 
 
 
 
 
 
 
 
 
 
 
 
76
  if question:
77
+ answer_a, answer_b, selected_functions = ProcessQuestion(question)
78
+ st.session_state["question"] = question
79
+ st.session_state["answer_a"] = answer_a
80
+ st.session_state["answer_b"] = answer_b
81
+ st.session_state["source_a"] = selected_functions[0].__name__
82
+ st.session_state["source_b"] = selected_functions[1].__name__
83
+ st.session_state["state"] = "arena_review"
84
+
85
+ def handle_vote(vote):
86
+ st.session_state["winner"] = vote
87
+ st.session_state["state"] = "arena_results"
88
+
89
+ def get_provider_info(provider_function_name):
90
+ provider_name_map = {
91
+ 'query_you_com': 'You.com',
92
+ 'query_tavily': 'Tavily',
93
+ 'query_perplexity': 'Perplexity AI',
94
+ 'query_brave': 'Brave Search'
95
+ }
96
+ provider_name = provider_name_map.get(provider_function_name)
97
+ return next((provider for provider in search_providers if provider['company_name'] == provider_name), {})
98
+
99
+ def render_ready_state():
100
+ st.text_area("Enter your question here (max 1000 characters):",
101
+ max_chars=1000,
102
+ key="question_input",
103
+ on_change=on_submit)
104
+ st.button("Submit", on_click=on_submit)
105
+
106
+ def render_review_state():
107
+ st.write("## Results")
108
  col1, col2 = st.columns(2)
109
  with col1:
110
+ st.write("### Answer A")
111
  st.write(st.session_state["answer_a"])
 
112
  with col2:
113
+ st.write("### Answer B")
114
  st.write(st.session_state["answer_b"])
115
+ st.write("### Vote for the Best Answer")
116
+ col1, col2, col3, col4 = st.columns(4)
117
+ if col1.button("It's a Tie 🤝"):
118
+ handle_vote("Tie")
119
+ if col2.button("A is better 💪"):
120
+ handle_vote("A")
121
+ if col3.button("B is better 🥇"):
122
+ handle_vote("B")
123
+ if col4.button("Both are bad 👎"):
124
+ handle_vote("Both are bad")
125
+
126
+ def render_results_state():
127
+ st.write("## Results")
128
+ st.write(f"### Question: {st.session_state['question']}")
129
+
130
+ provider_info_a = get_provider_info(st.session_state["source_a"])
131
+ provider_info_b = get_provider_info(st.session_state["source_b"])
132
+
133
+ col1, col2 = st.columns(2)
134
+ with col1:
135
+ if st.session_state["winner"] == "A":
136
+ st.write(f"### {provider_info_a['company_name']} 🥇")
137
+ elif st.session_state["winner"] == "Tie":
138
+ st.write(f"### 🤝 {provider_info_a['company_name']} 🤝")
139
+ elif st.session_state["winner"] == "Both are bad":
140
+ st.write(f"### 👎 {provider_info_a['company_name']} 👎")
141
+ else:
142
+ st.write(f"### {provider_info_a['company_name']} 🥈")
143
+ st.write("**Response:**")
144
+ st.markdown(f"<div style='padding: 10px; border: 1px solid #ddd;'>{st.session_state['answer_a']}</div>", unsafe_allow_html=True)
145
+
146
+ with col2:
147
+ if st.session_state["winner"] == "B":
148
+ st.write(f"### ⭐ {provider_info_b['company_name']} 🥇")
149
+ elif st.session_state["winner"] == "Tie":
150
+ st.write(f"### 🤝 {provider_info_b['company_name']} 🤝")
151
+ elif st.session_state["winner"] == "Both are bad":
152
+ st.write(f"### 👎 {provider_info_b['company_name']} 👎")
153
+ else:
154
+ st.write(f"### {provider_info_b['company_name']} 🥈")
155
+ st.write("**Response:**")
156
+ st.markdown(f"<div style='padding: 10px; border: 1px solid #ddd;'>{st.session_state['answer_b']}</div>", unsafe_allow_html=True)
157
+
158
+ st.write("### Feedback")
159
+ st.text_area("Please provide feedback on why you chose the winner:", key="feedback")
160
+ st.write("### About the search providers:")
161
+ col1, col2 = st.columns(2)
162
+ with col1:
163
+ st.write(f"**Website:** [{provider_info_a['website']}]({provider_info_a['website']})")
164
+ st.write(f"**Overview:** {provider_info_a['overview']}")
165
+ with col2:
166
+ st.write(f"**Website:** [{provider_info_b['website']}]({provider_info_b['website']})")
167
+ st.write(f"**Overview:** {provider_info_b['overview']}")
168
+
169
+ if st.session_state["state"] == "arena_ready":
170
+ render_ready_state()
171
+ elif st.session_state["state"] == "arena_review":
172
+ render_review_state()
173
+ elif st.session_state["state"] == "arena_results":
174
+ render_results_state()
175
+
176
+ # Apply custom CSS to highlight the selected button
177
+ selected_button = st.session_state.get("selected_button", "")
178
+
179
+ if selected_button:
180
+ st.markdown(
181
+ f"""
182
+ <style>
183
+ button[kind="primary"]{{
184
+ background-color: #4CAF50 !important;
185
+ color: white !important;
186
+ }}
187
+ </style>
188
+ """,
189
+ unsafe_allow_html=True
190
+ )
brave_ai.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import requests
3
+ from typing import List, Optional
4
+ # from langchain_community.document_transformers import MarkdownifyTransformer
5
+ from langchain_core.documents import Document
6
+ from langchain_core.pydantic_v1 import BaseModel, Field
7
+
8
+ class BraveAIWrapper(BaseModel):
9
+ api_key: str = Field(..., description="API key for Brave Search")
10
+ base_search_url: str = Field("https://api.search.brave.com/res/v1/web/search", const=True)
11
+ base_summarize_url: str = Field("https://api.search.brave.com/res/v1/summarizer/search", const=True)
12
+ headers: dict = Field(default_factory=dict, description="HTTP headers for API requests")
13
+
14
+ class Config:
15
+ arbitrary_types_allowed = True
16
+
17
+ def __init__(self, **data):
18
+ super().__init__(**data)
19
+ self.headers = {
20
+ "X-Subscription-Token": self.api_key,
21
+ "Accept": "application/json",
22
+ "Accept-Encoding": "gzip",
23
+ }
24
+
25
+ def get_brave_results(self, query: str, count: int = 3, safe_search: str = 'off') -> Optional[dict]:
26
+ """
27
+ Get search results from Brave Search.
28
+
29
+ Args:
30
+ query (str): The search query.
31
+ count (int): Number of results to return.
32
+ safe_search (str): Safe search filter (off, moderate, strict).
33
+
34
+ Returns:
35
+ Optional[dict]: JSON response from Brave Search API or None if an error occurs.
36
+ """
37
+ params = {
38
+ "q": query,
39
+ "count": count,
40
+ "summary": True,
41
+ "safe_search": safe_search,
42
+ "extra_snippets": True,
43
+ }
44
+ try:
45
+ response = requests.get(self.base_search_url, headers=self.headers, params=params)
46
+ response.raise_for_status()
47
+ return response.json()
48
+ except requests.exceptions.RequestException as e:
49
+ print(f"Error: {e}")
50
+ return None
51
+
52
+ def summarize_results(self, summarizer_key: str) -> Optional[dict]:
53
+ """
54
+ Summarize search results using Brave Summarizer.
55
+
56
+ Args:
57
+ summarizer_key (str): The key for the summarizer.
58
+
59
+ Returns:
60
+ Optional[dict]: JSON response from Brave Summarizer API or None if an error occurs.
61
+ """
62
+ params = {"key": summarizer_key}
63
+ try:
64
+ response = requests.get(self.base_summarize_url, headers=self.headers, params=params)
65
+ response.raise_for_status()
66
+ return response.json()
67
+ except requests.exceptions.RequestException as e:
68
+ print(f"Error: {e}")
69
+ return None
70
+
71
+ def get_and_summarize(self, query: str, count: int = 3, safe_search: str = 'off') -> Optional[str]:
72
+ """
73
+ Get and summarize search results from Brave Search.
74
+
75
+ Args:
76
+ query (str): The search query.
77
+ count (int): Number of results to return.
78
+ safe_search (str): Safe search filter (off, moderate, strict).
79
+
80
+ Returns:
81
+ Optional[str]: Summarized result or None if an error occurs.
82
+ """
83
+ results = self.get_brave_results(query, count, safe_search)
84
+ if results and 'summarizer' in results:
85
+ summarizer_key = results['summarizer']['key']
86
+ summary = self.summarize_results(summarizer_key)
87
+ if summary and 'summary' in summary and len(summary['summary']) > 0:
88
+ return summary['summary'][0]['data']
89
+ return None
helpers.py CHANGED
@@ -1,5 +1,6 @@
1
  import requests
2
  from dotenv import load_dotenv
 
3
  import os
4
 
5
  # Load environment variables from .env file
@@ -9,8 +10,7 @@ load_dotenv()
9
  YOU_COM_API_KEY = os.getenv("YOU_API_KEY")
10
  TAVILY_API_KEY = os.getenv("TAVILY_API_KEY")
11
  PERPLEXITY_API_KEY = os.getenv("PPLX_API_KEY")
12
- BRAVE_API_KEY = os.getenv("BRAVESEARCH_API_KEY")
13
-
14
 
15
  def query_you_com(query):
16
  headers = {"X-API-Key": YOU_COM_API_KEY}
@@ -76,71 +76,6 @@ def query_perplexity(query):
76
  return f"Request failed with status code: {response.status_code}"
77
 
78
 
79
- # def query_brave(query):
80
- # headers = {"X-API-Key": BRAVE_API_KEY}
81
- # params = {
82
- # "q": query,
83
- # "count": 1,
84
- # "summary": True
85
- # }
86
- # response = requests.get("https://api.search.brave.com/res/v1/web/search", params=params, headers=headers)
87
- # if response.status_code == 200:
88
- # return response.json().get("summary", "No summary available.")
89
- # else:
90
- # return f"Request failed with status code: {response}"
91
-
92
-
93
- # def brave_search_summarization(query):
94
- # # Endpoint for web search with summary
95
- # web_search_url = "https://api.search.brave.com/res/v1/web/search"
96
- # summarizer_url = "https://api.search.brave.com/res/v1/summarizer/search"
97
-
98
- # # Headers for the requests
99
- # headers = {
100
- # "Accept": "application/json",
101
- # "Accept-Encoding": "gzip",
102
- # "X-Subscription-Token": BRAVE_API_KEY
103
- # }
104
-
105
- # # Parameters for the initial web search request
106
- # web_search_params = {
107
- # "q": query,
108
- # "summary": 1
109
- # }
110
-
111
- # # Make the initial request to the web search endpoint
112
- # web_search_response = requests.get(web_search_url, headers=headers, params=web_search_params)
113
-
114
- # # Check if the request was successful
115
- # if web_search_response.status_code != 200:
116
- # raise Exception(f"Web search request failed with status code {web_search_response.status_code}")
117
-
118
- # web_search_data = web_search_response.json()
119
-
120
- # # Extract the summarizer key from the response
121
- # summarizer_key = web_search_data.get('summarizer', {}).get('key')
122
- # if not summarizer_key:
123
- # raise Exception("No summarizer key found in the web search response")
124
-
125
- # # Parameters for the summarizer request
126
- # summarizer_params = {
127
- # "key": summarizer_key,
128
- # "entity_info": 1
129
- # }
130
-
131
- # # Make the request to the summarizer endpoint
132
- # summarizer_response = requests.get(summarizer_url, headers=headers, params=summarizer_params)
133
-
134
- # # Check if the request was successful
135
- # if summarizer_response.status_code != 200:
136
- # raise Exception(f"Summarizer request failed with status code {summarizer_response.status_code}")
137
-
138
- # summarizer_data = summarizer_response.json()
139
-
140
- # # Return the summarized content
141
- # return summarizer_data
142
-
143
-
144
  def ProcessQuestion(question, model):
145
  if model == "You.com":
146
  return query_you_com(question)
@@ -152,3 +87,21 @@ def ProcessQuestion(question, model):
152
  return query_brave(question)
153
  else:
154
  return "Model not supported"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import requests
2
  from dotenv import load_dotenv
3
+ from typing import Optional
4
  import os
5
 
6
  # Load environment variables from .env file
 
10
  YOU_COM_API_KEY = os.getenv("YOU_API_KEY")
11
  TAVILY_API_KEY = os.getenv("TAVILY_API_KEY")
12
  PERPLEXITY_API_KEY = os.getenv("PPLX_API_KEY")
13
+ BRAVE_API_KEY = os.getenv("BRAVE_AI_API_KEY")
 
14
 
15
  def query_you_com(query):
16
  headers = {"X-API-Key": YOU_COM_API_KEY}
 
76
  return f"Request failed with status code: {response.status_code}"
77
 
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  def ProcessQuestion(question, model):
80
  if model == "You.com":
81
  return query_you_com(question)
 
87
  return query_brave(question)
88
  else:
89
  return "Model not supported"
90
+
91
+
92
+ from brave_ai import BraveAIWrapper
93
+
94
+ def query_brave(query: str) -> Optional[str]:
95
+ """
96
+ Get a summary for the given query using BraveAIWrapper.
97
+
98
+ Args:
99
+ query (str): The search query.
100
+ api_key (str): The API key for Brave Search.
101
+
102
+ Returns:
103
+ Optional[str]: Summarized result or None if an error occurs.
104
+ """
105
+ brave_ai = BraveAIWrapper(api_key=BRAVE_API_KEY)
106
+ summary = brave_ai.get_and_summarize(query)
107
+ return summary
provider_info.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ search_providers = [
2
+ { "company_name": "You.com",
3
+ "website": "you.com",
4
+ "overview": "You.com is an AI-powered search engine and productivity tool that aims to provide users with more control, privacy, and customization over their online search experience. Founded in 2020 by Richard Socher, former Chief Scientist at Salesforce, and Bryan McCann, You.com has evolved from a privacy-focused search engine into an AI assistant that supports chat-based search.\n\nKey features of You.com include:\n\n- AI Modes: You.com offers different AI interaction modes tailored to user needs, such as Smart mode for quick tasks and summarization, Genius mode for complex queries requiring multi-step reasoning, and Research mode for in-depth analysis with extensive citations.\n\n- Multimodal search: Beyond text, You.com can generate AI art, data visualizations, and even run Python code to solve math and science questions. It was one of the first search engines to introduce multimodal AI chat capabilities.\n\n- Customization: Users can personalize their search experience by selecting preferred sources, adjusting AI model parameters, and leveraging You.com's developer platform to build custom apps and integrations.\n\n- Privacy: You.com does not track users or sell their personal data. It provides a more secure and private alternative to mainstream search engines.\n\n- Subscription model: While offering a free tier, You.com provides a premium subscription called YouPro that unlocks advanced AI features, unlimited access, and an ad-free experience.\n\nYou.com has gained significant traction, amassing millions of users and raising substantial funding from prominent investors like Salesforce CEO Marc Benioff. In 2023, the company raised $45 million at a $700-900 million valuation.\n\nUnder the leadership of Richard Socher, who was named to Time's TIME100 AI list in 2023, You.com aims to make information more accessible and enhance user productivity through cutting-edge AI technologies. Its unique blend of search and AI assistance capabilities positions You.com as a major player in the rapidly evolving search and productivity tools market.\n\nIn summary, You.com is a next-generation AI search assistant that combines the power of large language models with live web access to deliver highly relevant, contextual, and multimodal search results while prioritizing user privacy and customization. By making information discovery more intuitive and empowering, You.com is reshaping the future of search."
5
+ },
6
+ { "company_name": "Tavily",
7
+ "website": "tavily.com",
8
+ "overview": "Tavily is an AI-powered search API and research platform designed specifically for large language models (LLMs) and AI agents. It aims to provide efficient, accurate, and factual search results to enhance the capabilities of AI applications.\n\nKey features of Tavily include:\n\n- Optimized for LLMs: Tavily's search API is tailored for AI agents and delivers real-time, relevant results to reduce hallucinations and bias in AI-generated content.\n\n- In-depth research: It simplifies data gathering by providing aggregated and curated results from multiple sources in a single API call. Tavily searches over 20+ sites per query and uses AI to score, filter, and rank the most relevant content.\n\n- Intelligent query suggestions: Tavily equips AI agents with the ability to iteratively deepen their knowledge through automated, nuanced answers and follow-up query suggestions.\n\n- Customization: The API offers customizable search depths, domain management, and HTML content parsing controls. It can be integrated with any LLM or used with partners like Langchain and LlamaIndex.\n\n- Versatility: Beyond fetching results, Tavily can answer questions, enable cross-agent communication, and complete comprehensive research tasks in seconds by leveraging proprietary data sources.\n\nTavily caters to a range of users, from new creators and researchers to solopreneurs, small teams, and enterprise-level needs. By automating the tedious aspects of online research like searching, scraping, filtering, and extracting relevant information, Tavily enables users to save time and make more informed decisions.\n\nIn summary, Tavily is a powerful AI search and research tool that connects LLMs and AI applications to trusted, real-time knowledge to enhance their performance and capabilities. It streamlines the research workflow and delivers comprehensive, accurate results to your inbox within minutes."
9
+ },
10
+ {"company_name": "Perplexity AI",
11
+ "website": "perplexity.ai",
12
+ "overview": "Perplexity AI is an AI-powered conversational search engine that provides accurate, concise answers to user queries by searching the web in real-time and leveraging advanced natural language processing capabilities. It aims to make information more accessible and understandable.\n\nKey features of Perplexity AI include:\n\n- Conversational interface: Users can engage with Perplexity AI using natural language, making information discovery as easy as having a conversation. It understands context and nuance to provide relevant answers.\n\n- Transparent sourcing: Perplexity AI cites the sources it uses to generate answers, enabling users to verify information and explore topics further. It aims to build trust through transparency.\n\n- Personalized results: The more a user interacts with Perplexity AI, the more it learns about their interests and preferences, allowing it to tailor future search results and recommendations.\n\n- Multi-model architecture: Perplexity AI utilizes multiple large language models, including GPT-4, Claude, and its own proprietary models, to process queries and generate human-like responses.\n\n- Versatility: Beyond answering questions, Perplexity AI can assist with a wide range of tasks such as writing, coding, analyzing data, and creative projects. It adapts to the user's needs.\n\n- Continuous learning: By indexing the web daily, Perplexity AI stays up-to-date with the latest information to provide relevant, timely answers.\n\nPerplexity AI caters to a broad user base, including researchers, writers, programmers, and curious individuals seeking to learn and explore. It has gained significant traction, amassing over 10 million monthly users as of early 2024.\n\nFounded in 2022 by a team with experience from Google, OpenAI, and other leading tech companies, Perplexity AI has raised over $165 million from prominent investors. Its mission is to democratize access to knowledge and empower people to learn in their own way.\n\nIn summary, Perplexity AI is a powerful AI search engine that combines advanced language understanding, real-time web indexing, and an intuitive conversational interface to deliver accurate, relevant answers and support a wide range of information needs. By making knowledge more accessible and engaging, it is transforming how people discover, learn, and create."
13
+ },
14
+ {"company_name": "Brave Search",
15
+ "website": "search.brave.com",
16
+ "overview": "Brave Search is a privacy-focused search engine that offers an AI API for developers to integrate search capabilities and generate summaries from search results. The API leverages Brave's own search index and AI models to provide relevant, accurate, and concise information.\n\nKey features of Brave Search's AI API include:\n\n- Two-step process: To use the API, developers first perform a search using the '/search' endpoint, which returns a list of relevant web pages. They can then pass the search results to the '/summarize' endpoint to generate a summary of the information.\n\n- Search quality: Brave Search maintains its own independent search index, ensuring that results are not influenced by biased algorithms or user tracking. The search functionality of the API delivers high-quality, relevant web pages for a given query.\n\n- Summarization: The '/summarize' endpoint uses advanced AI language models to analyze the content of the web pages returned by the search and generate a concise, coherent summary. This saves developers time and effort in extracting key information from search results.\n\n- Customization: Developers can fine-tune the search and summarization process by adjusting parameters such as the number of search results to consider, the length of the summary, and the focus of the summary (e.g., key facts, main ideas, or specific details).\n\n- Privacy: In line with Brave's commitment to privacy, the AI API does not track users or collect personal data. All searches and summarization requests are processed anonymously.\n\nBrave Search's AI API is suitable for a wide range of applications, such as content aggregation platforms, research tools, news summarization services, and chatbots. By providing access to Brave's search capabilities and AI-powered summarization, the API enables developers to create innovative, privacy-respecting applications that deliver valuable insights to users.\n\nThe API offers a free tier with limited requests and a paid tier for higher usage and additional features. Brave Search is committed to expanding the capabilities of its AI API and supporting developers in building next-generation search and language AI applications.\n\nIn summary, Brave Search's AI API combines the power of privacy-focused search with advanced AI summarization capabilities, allowing developers to integrate high-quality search results and concise summaries into their applications. By providing a two-step process of searching and summarizing, the API streamlines information retrieval and synthesis, while prioritizing user privacy."
17
+ }
18
+ ]
requirements.txt CHANGED
@@ -1,6 +1,92 @@
1
- swarms
2
- exa_py
3
- tavily-python
4
- openai
5
- exa_py
6
- pymongo
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiohttp==3.9.5
2
+ altair==5.3.0
3
+ anyio==4.4.0
4
+ attrs==23.2.0
5
+ beautifulsoup4==4.12.3
6
+ blinker==1.8.2
7
+ cachetools==5.3.2
8
+ certifi==2024.6.2
9
+ charset-normalizer==3.3.2
10
+ click==8.1.7
11
+ dataclasses-json==0.6.7
12
+ dnspython==2.6.1
13
+ email_validator==2.1.2
14
+ fastapi==0.111.0
15
+ filelock==3.15.1
16
+ frozenlist==1.4.1
17
+ fsspec==2024.6.0
18
+ gitdb==4.0.11
19
+ GitPython==3.1.43
20
+ google-api-core==2.15.0
21
+ google-auth==2.26.2
22
+ google-cloud-aiplatform==1.39.0
23
+ google-cloud-bigquery==3.16.0
24
+ google-cloud-core==2.4.1
25
+ google-cloud-resource-manager==1.11.0
26
+ google-cloud-storage==2.14.0
27
+ google-crc32c==1.5.0
28
+ google-resumable-media==2.7.0
29
+ googleapis-common-protos==1.62.0
30
+ grpc-google-iam-v1==0.13.0
31
+ grpcio-status==1.60.0
32
+ h11==0.14.0
33
+ httpcore==1.0.5
34
+ httptools==0.6.1
35
+ httpx==0.27.0
36
+ huggingface-hub==0.23.4
37
+ idna==3.7
38
+ Jinja2==3.1.4
39
+ jsonpatch==1.33
40
+ jsonpointer==3.0.0
41
+ jsonschema==4.22.0
42
+ langchain==0.1.13
43
+ loguru==0.7.2
44
+ markdown-it-py==3.0.0
45
+ markdownify==0.12.1
46
+ MarkupSafe==2.1.5
47
+ marshmallow==3.21.3
48
+ multidict==6.0.5
49
+ networkx==3.3
50
+ numpy==1.26.4
51
+ openai==1.34.0
52
+ orjson==3.10.5
53
+ packaging==23.2
54
+ pandas==2.2.2
55
+ pillow==10.3.0
56
+ proto-plus==1.23.0
57
+ protobuf==4.25.3
58
+ pymongo==4.7.3
59
+ pypdf==4.1.0
60
+ python-dotenv==1.0.1
61
+ pytz==2024.1
62
+ PyYAML==6.0.1
63
+ ratelimit==2.2.1
64
+ referencing==0.35.1
65
+ requests==2.32.3
66
+ rich==13.7.1
67
+ rsa==4.9
68
+ safetensors==0.4.3
69
+ sentry-sdk==2.5.1
70
+ shapely==2.0.2
71
+ six==1.16.0
72
+ sniffio==1.3.1
73
+ soupsieve==2.5
74
+ SQLAlchemy==2.0.30
75
+ starlette==0.37.2
76
+ streamlit==1.35.0
77
+ sympy==1.12.1
78
+ tenacity==8.3.0
79
+ termcolor==2.4.0
80
+ tqdm==4.66.4
81
+ transformers==4.41.2
82
+ typer==0.12.3
83
+ typing-inspect==0.9.0
84
+ typing_extensions==4.8.0
85
+ tzdata==2024.1
86
+ ujson==5.10.0
87
+ urllib3==2.2.1
88
+ uvicorn==0.30.1
89
+ uvloop==0.19.0
90
+ watchfiles==0.22.0
91
+ websockets==12.0
92
+ yarl==1.9.4
test_func.py CHANGED
@@ -24,7 +24,43 @@ def test_queries():
24
  # print("\nTesting Brave.com API:")
25
  # brave_result = brave_search_summarization(test_query)
26
  # print(brave_result)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
 
29
  if __name__ == "__main__":
30
  test_queries()
 
 
24
  # print("\nTesting Brave.com API:")
25
  # brave_result = brave_search_summarization(test_query)
26
  # print(brave_result)
27
+
28
+ def test_brave_ai_wrapper():
29
+ # Initialize the BraveAIWrapper with your API key
30
+ api_key = "your_api_key_here"
31
+ brave_ai = BraveAIWrapper(api_key=api_key)
32
+
33
+ # Define the test query
34
+ query = "What is some of the best mountain biking near Crested Butte, CO?"
35
+
36
+ # Test get_brave_results
37
+ print("Testing get_brave_results...")
38
+ results = brave_ai.get_brave_results(query)
39
+ if results:
40
+ print("get_brave_results output:", json.dumps(results, indent=2))
41
+ else:
42
+ print("get_brave_results failed.")
43
+
44
+ # Test get_and_summarize
45
+ print("\nTesting get_and_summarize...")
46
+ summary = brave_ai.get_and_summarize(query)
47
+ if summary:
48
+ print("get_and_summarize output:", summary)
49
+ else:
50
+ print("get_and_summarize failed.")
51
+
52
+ # Test download_documents
53
+ print("\nTesting download_documents...")
54
+ documents = brave_ai.download_documents(query)
55
+ if documents:
56
+ for doc in documents:
57
+ print("Document metadata:", doc.metadata)
58
+ print("Document content:", doc.page_content[:200]) # Print first 200 characters
59
+ print("-" * 40)
60
+ else:
61
+ print("download_documents failed.")
62
 
63
 
64
  if __name__ == "__main__":
65
  test_queries()
66
+ test_brave_ai_wrapper()