Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -1,5 +1,204 @@
|
|
1 |
-
|
2 |
-
from
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
|
4 |
if __name__ == "__main__":
|
5 |
run_gradio_interface()
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from swarm import Swarm, Agent
|
3 |
+
from openai import OpenAI
|
4 |
+
from exa_py import Exa
|
5 |
+
import os
|
6 |
+
from dotenv import load_dotenv
|
7 |
+
import tweepy
|
8 |
+
import json
|
9 |
+
|
10 |
+
load_dotenv()
|
11 |
+
|
12 |
+
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
13 |
+
client = Swarm(client=openai_client)
|
14 |
+
exa_client = Exa(api_key=os.getenv("EXA_API_KEY"))
|
15 |
+
|
16 |
+
# Twitter API setup
|
17 |
+
bearer_token = os.getenv('bearer_token')
|
18 |
+
twitter_client = tweepy.Client(bearer_token=bearer_token)
|
19 |
+
|
20 |
+
def search_prop_firm_info(query, num_results=5):
|
21 |
+
results = exa_client.search_and_contents(
|
22 |
+
query,
|
23 |
+
type="keyword",
|
24 |
+
num_results=int(num_results),
|
25 |
+
text=True,
|
26 |
+
start_published_date="2023-01-01",
|
27 |
+
category="company",
|
28 |
+
include_domains=["propfirmmatch.com"],
|
29 |
+
summary=True
|
30 |
+
)
|
31 |
+
formatted_results = []
|
32 |
+
for result in results.results:
|
33 |
+
formatted_results.append(f"Title: {result.title}\nURL: {result.url}\nSummary: {result.summary}\n")
|
34 |
+
return "\n".join(formatted_results)
|
35 |
+
|
36 |
+
def search_trustpilot_reviews(company_name, num_results=3):
|
37 |
+
query = f"site:trustpilot.com {company_name} reviews"
|
38 |
+
results = exa_client.search_and_contents(
|
39 |
+
query,
|
40 |
+
type="keyword",
|
41 |
+
num_results=int(num_results),
|
42 |
+
text=True,
|
43 |
+
start_published_date="2023-01-01",
|
44 |
+
summary=True
|
45 |
+
)
|
46 |
+
formatted_results = []
|
47 |
+
for result in results.results:
|
48 |
+
formatted_results.append(f"Title: {result.title}\nURL: {result.url}\nSummary: {result.summary}\n")
|
49 |
+
return "\n".join(formatted_results)
|
50 |
+
|
51 |
+
def search_tweets(query, max_results=100):
|
52 |
+
try:
|
53 |
+
formatted_query = query.replace('"', '').strip()
|
54 |
+
tweets = twitter_client.search_recent_tweets(query=formatted_query, max_results=max_results)
|
55 |
+
return tweets.data if tweets.data else []
|
56 |
+
except tweepy.errors.BadRequest as e:
|
57 |
+
print(f"BadRequest error: {e}")
|
58 |
+
return []
|
59 |
+
except tweepy.errors.TweepyException as e:
|
60 |
+
print(f"Tweepy error: {e}")
|
61 |
+
return []
|
62 |
+
except Exception as e:
|
63 |
+
print(f"Unexpected error in search_tweets: {e}")
|
64 |
+
return []
|
65 |
+
|
66 |
+
twitter_sentiment_agent = Agent(
|
67 |
+
name="Twitter Sentiment Analyzer",
|
68 |
+
instructions="""You are an agent that analyzes Twitter sentiment for proprietary trading firms.
|
69 |
+
Given a list of tweets about a specific firm, analyze the overall sentiment and provide a summary.
|
70 |
+
Consider the following:
|
71 |
+
1. Overall sentiment (positive, negative, or neutral)
|
72 |
+
2. Common themes or topics mentioned
|
73 |
+
3. Any notable praise or complaints
|
74 |
+
4. Level of engagement (replies, retweets, likes)
|
75 |
+
Provide a concise summary of your findings.""",
|
76 |
+
functions=[search_tweets],
|
77 |
+
)
|
78 |
+
|
79 |
+
trustpilot_review_agent = Agent(
|
80 |
+
name="TrustPilot Review Analyzer",
|
81 |
+
instructions="""You are an agent that searches for and analyzes TrustPilot reviews for proprietary trading firms.
|
82 |
+
Use the search_trustpilot_reviews function to find reviews for a given company.
|
83 |
+
Your tasks are to:
|
84 |
+
1. Search for TrustPilot reviews using the provided company name.
|
85 |
+
2. Analyze the overall sentiment of the reviews (positive, negative, or mixed).
|
86 |
+
3. Identify common themes or recurring points in the reviews.
|
87 |
+
4. Note any standout positive or negative comments.
|
88 |
+
5. If available, mention the overall TrustPilot rating for the company.
|
89 |
+
6. Provide a concise summary of your findings, highlighting the most important aspects for a potential trader.
|
90 |
+
|
91 |
+
Your summary should be informative and balanced, presenting both positives and negatives if they exist.""",
|
92 |
+
functions=[search_trustpilot_reviews],
|
93 |
+
)
|
94 |
+
|
95 |
+
prop_firm_search_agent = Agent(
|
96 |
+
name="Prop Firm Search",
|
97 |
+
instructions="""You are an agent that searches for proprietary trading firm information on propfirmmatch.com. Use the search_prop_firm_info function to find information based on the user's query. The function takes two parameters: query (string) and num_results (integer, default 5).
|
98 |
+
If the user names a specific firm:
|
99 |
+
1. Use the firm's name as the search query.
|
100 |
+
2. Call the search_prop_firm_info function with the firm's name.
|
101 |
+
3. Provide a detailed summary of the information found about the firm from propfirmmatch.com.
|
102 |
+
Always include relevant details such as leverage, accepted countries, and any unique features of the firms.""",
|
103 |
+
functions=[search_prop_firm_info],
|
104 |
+
)
|
105 |
+
|
106 |
+
score_agent = Agent(
|
107 |
+
name="Score Generator",
|
108 |
+
instructions="""You are an agent that generates an overall score for proprietary trading firms based on the information provided.
|
109 |
+
Consider the following factors:
|
110 |
+
1. Information from propfirmmatch.com
|
111 |
+
2. TrustPilot reviews
|
112 |
+
3. Twitter sentiment
|
113 |
+
4. Any unique features or advantages of the firm
|
114 |
+
|
115 |
+
Generate a score out of 100, where:
|
116 |
+
90-100: Excellent
|
117 |
+
80-89: Very Good
|
118 |
+
70-79: Good
|
119 |
+
60-69: Fair
|
120 |
+
Below 60: Poor
|
121 |
+
|
122 |
+
Provide a brief explanation for the score.
|
123 |
+
|
124 |
+
Format your response as follows:
|
125 |
+
**Score:** (your score here)
|
126 |
+
**Twitter:** (Highlights of twitter analysis here)
|
127 |
+
**TrustPilot:** (Highlights / notable reviews here)
|
128 |
+
**PropFirmMatch:** (Summary of firm from search_propfirm_info / propfirmmatch agent)""",
|
129 |
+
functions=[],
|
130 |
+
)
|
131 |
+
|
132 |
+
def fetch_twitter_sentiment(company_name, num_tweets=100):
|
133 |
+
query = f"{company_name} -is:retweet"
|
134 |
+
tweets = search_tweets(query, max_results=num_tweets)
|
135 |
+
|
136 |
+
if not tweets:
|
137 |
+
return "No tweets found."
|
138 |
+
|
139 |
+
tweet_texts = [tweet.text for tweet in tweets]
|
140 |
+
tweet_data = "\n\n".join(tweet_texts)
|
141 |
+
|
142 |
+
analysis_prompt = f"Analyze the sentiment of the following tweets about {company_name}:\n\n{tweet_data}"
|
143 |
+
|
144 |
+
sentiment_response = client.run(twitter_sentiment_agent, messages=[{"role": "user", "content": analysis_prompt}])
|
145 |
+
sentiment_analysis = sentiment_response.messages[-1]["content"] if sentiment_response.messages else "No sentiment analysis available."
|
146 |
+
|
147 |
+
return sentiment_analysis
|
148 |
+
|
149 |
+
def search_prop_firms(query):
|
150 |
+
search_response = client.run(prop_firm_search_agent, messages=[{"role": "user", "content": query}])
|
151 |
+
search_results = search_response.messages[-1]["content"] if search_response.messages else "No search results."
|
152 |
+
|
153 |
+
trustpilot_analysis = get_trustpilot_analysis(query)
|
154 |
+
twitter_sentiment = fetch_twitter_sentiment(query)
|
155 |
+
|
156 |
+
combined_results = f"{search_results}\n\nTrustPilot Analysis:\n{trustpilot_analysis}\n\nTwitter Sentiment Analysis:\n{twitter_sentiment}"
|
157 |
+
|
158 |
+
score_prompt = f"Generate a score for {query} based on the following information:\n\n{combined_results}"
|
159 |
+
score_response = client.run(score_agent, messages=[{"role": "user", "content": score_prompt}])
|
160 |
+
score_result = score_response.messages[-1]["content"] if score_response.messages else "No score available."
|
161 |
+
|
162 |
+
return query, search_results, trustpilot_analysis, twitter_sentiment, score_result
|
163 |
+
|
164 |
+
def get_trustpilot_analysis(firm_name):
|
165 |
+
trustpilot_prompt = f"Find and analyze TrustPilot reviews for {firm_name}"
|
166 |
+
trustpilot_response = client.run(trustpilot_review_agent, messages=[{"role": "user", "content": trustpilot_prompt}])
|
167 |
+
return trustpilot_response.messages[-1]["content"] if trustpilot_response.messages else "No TrustPilot analysis available."
|
168 |
+
|
169 |
+
def format_report_card(query):
|
170 |
+
firm_name, search_results, trustpilot_analysis, twitter_sentiment, score_result = search_prop_firms(query)
|
171 |
+
|
172 |
+
report_card = {
|
173 |
+
"firm_name": firm_name,
|
174 |
+
"overall_score": score_result,
|
175 |
+
"firm_info": search_results,
|
176 |
+
"trustpilot_analysis": trustpilot_analysis,
|
177 |
+
"twitter_sentiment": twitter_sentiment
|
178 |
+
}
|
179 |
+
|
180 |
+
return json.dumps(report_card)
|
181 |
+
|
182 |
+
def run_gradio_interface():
|
183 |
+
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
184 |
+
gr.Markdown("# Proprietary Trading Firm Analysis")
|
185 |
+
|
186 |
+
with gr.Row():
|
187 |
+
with gr.Column(scale=2):
|
188 |
+
query_input = gr.Textbox(label="Enter firm name", lines=2)
|
189 |
+
search_button = gr.Button("Generate Report", variant="primary")
|
190 |
+
with gr.Column(scale=1):
|
191 |
+
gr.Markdown("### Example Queries")
|
192 |
+
gr.Examples(
|
193 |
+
examples=["FTMO", "MyForexFunds", "The5ers"],
|
194 |
+
inputs=query_input
|
195 |
+
)
|
196 |
+
|
197 |
+
output = gr.JSON(label="Report Card")
|
198 |
+
|
199 |
+
search_button.click(format_report_card, inputs=[query_input], outputs=[output])
|
200 |
+
|
201 |
+
demo.launch(share=True)
|
202 |
|
203 |
if __name__ == "__main__":
|
204 |
run_gradio_interface()
|