aidevhund commited on
Commit
3182722
·
verified ·
1 Parent(s): e60bef3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -11
app.py CHANGED
@@ -2,19 +2,47 @@ import gradio as gr
2
  import openai
3
  import os
4
  import base64
 
 
 
 
5
 
6
  # OpenAI API Configuration
7
  openai.api_key = os.getenv("OPENAI_API_KEY")
8
  ANALYSIS_MODEL = "gpt-4o"
9
  MAX_TOKENS = 4096
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  # System Prompt Configuration
12
  SYSTEM_PROMPT = """Professional Crypto Technical Analyst:
13
  1. Identify all technical patterns in the chart
14
  2. Determine key support/resistance levels
15
  3. Analyze volume and momentum indicators
16
  4. Calculate risk/reward ratios
17
- 5. Provide clear trading recommendations
18
  6. Include specific price targets
19
  7. Assess market sentiment
20
  8. Evaluate trend strength
@@ -22,6 +50,46 @@ SYSTEM_PROMPT = """Professional Crypto Technical Analyst:
22
  10. Provide time-based projections"""
23
 
24
  class ChartAnalyzer:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  def encode_image(self, image_path: str) -> str:
26
  """Encode image to base64 with validation"""
27
  if not os.path.exists(image_path):
@@ -34,17 +102,24 @@ class ChartAnalyzer:
34
  with open(image_path, "rb") as image_file:
35
  return base64.b64encode(image_file.read()).decode('utf-8')
36
 
37
- def analyze_chart(self, image_path: str) -> str:
38
- """Core analysis function"""
 
39
  try:
40
- base64_image = self.encode_image(image_path)
 
 
 
 
 
 
41
 
42
  response = openai.ChatCompletion.create(
43
  model=ANALYSIS_MODEL,
44
  messages=[
45
  {
46
  "role": "system",
47
- "content": SYSTEM_PROMPT
48
  },
49
  {
50
  "role": "user",
@@ -196,12 +271,10 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
196
  gr.Markdown("""
197
  <div style="text-align: center; margin-bottom: 32px;">
198
  <h1 style="color: var(--primary-color); font-size: 2.5rem; margin-bottom: 16px;">
199
- 🧠 HundAI Q-Agent
200
  </h1>
201
  <p style="color: var(--text-color); font-size: 1.1rem;">
202
- Advanced Multifunctional HundAI-powered cryptocurrency technical analysis<br>
203
- 🔍 Deep Pattern Recognition<br>
204
- 🤖 Neural Market Forecasting
205
  </p>
206
  </div>
207
  """)
@@ -218,6 +291,11 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
218
  sources=["upload"],
219
  height=300
220
  )
 
 
 
 
 
221
  analyze_btn = gr.Button(
222
  "Analyze Chart",
223
  variant="primary",
@@ -236,12 +314,12 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
236
 
237
  # Event Handling
238
  analyze_btn.click(
239
- fn=lambda: "Generating report...", # Show loading text immediately
240
  outputs=analysis_output,
241
  queue=False
242
  ).then(
243
  fn=analyzer.analyze_chart,
244
- inputs=chart_input,
245
  outputs=analysis_output,
246
  api_name="analyze"
247
  )
 
2
  import openai
3
  import os
4
  import base64
5
+ from functools import lru_cache
6
+ from PIL import Image
7
+ import cv2
8
+ import numpy as np
9
 
10
  # OpenAI API Configuration
11
  openai.api_key = os.getenv("OPENAI_API_KEY")
12
  ANALYSIS_MODEL = "gpt-4o"
13
  MAX_TOKENS = 4096
14
 
15
+ # Persona Definitions
16
+ PERSONAS = {
17
+ "Aggressive Trader": {
18
+ "description": "High-risk, short-term gains, leverages volatile market movements.",
19
+ "prompt": "Focus on high-risk strategies, short-term gains, and leverage opportunities. Suggest aggressive entry and exit points."
20
+ },
21
+ "Conservative Trader": {
22
+ "description": "Low-risk, long-term investments, prioritizes capital preservation.",
23
+ "prompt": "Focus on low-risk strategies, long-term investments, and capital preservation. Suggest safe entry points and strict stop-loss levels."
24
+ },
25
+ "Neutral Trader": {
26
+ "description": "Balanced approach, combines short and long-term strategies.",
27
+ "prompt": "Focus on balanced strategies, combining short and long-term opportunities. Suggest moderate risk levels and trend-following approaches."
28
+ },
29
+ "Reactive Trader": {
30
+ "description": "Quick decisions based on market news and social media trends.",
31
+ "prompt": "Focus on quick decision-making, momentum trading, and reacting to market news. Suggest strategies based on current trends and FOMO opportunities."
32
+ },
33
+ "Systematic Trader": {
34
+ "description": "Algorithm-based, rule-driven, and emotionless trading.",
35
+ "prompt": "Focus on algorithmic strategies, backtested rules, and quantitative analysis. Suggest data-driven entry and exit points."
36
+ }
37
+ }
38
+
39
  # System Prompt Configuration
40
  SYSTEM_PROMPT = """Professional Crypto Technical Analyst:
41
  1. Identify all technical patterns in the chart
42
  2. Determine key support/resistance levels
43
  3. Analyze volume and momentum indicators
44
  4. Calculate risk/reward ratios
45
+ 5. Provide clear trading recommendations based on the selected persona
46
  6. Include specific price targets
47
  7. Assess market sentiment
48
  8. Evaluate trend strength
 
50
  10. Provide time-based projections"""
51
 
52
  class ChartAnalyzer:
53
+ def __init__(self):
54
+ self.last_analysis = ""
55
+
56
+ def validate_image(self, image_path: str) -> bool:
57
+ """Validate if the uploaded file is a valid image and looks like a chart"""
58
+ try:
59
+ # Check if the file is an image
60
+ with Image.open(image_path) as img:
61
+ img.verify() # Verify that it is a valid image
62
+
63
+ # Check if the image looks like a chart (basic check)
64
+ img = cv2.imread(image_path)
65
+ if img is None:
66
+ return False
67
+
68
+ # Simple check for chart-like features (e.g., axes, grid lines)
69
+ gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
70
+ edges = cv2.Canny(gray, 50, 150)
71
+ if np.sum(edges) < 1000: # Arbitrary threshold for edge detection
72
+ return False
73
+
74
+ return True
75
+ except Exception:
76
+ return False
77
+
78
+ def optimize_image(self, image_path: str) -> str:
79
+ """Optimize image size and quality"""
80
+ try:
81
+ img = Image.open(image_path)
82
+ # Resize if the image is too large
83
+ if img.size[0] > 1024 or img.size[1] > 1024:
84
+ img = img.resize((1024, 1024), Image.ANTIALIAS)
85
+ # Save optimized image
86
+ optimized_path = "optimized_chart.png"
87
+ img.save(optimized_path, "PNG", optimize=True, quality=85)
88
+ return optimized_path
89
+ except Exception as e:
90
+ print(f"Image optimization error: {str(e)}")
91
+ return image_path # Fallback to original image
92
+
93
  def encode_image(self, image_path: str) -> str:
94
  """Encode image to base64 with validation"""
95
  if not os.path.exists(image_path):
 
102
  with open(image_path, "rb") as image_file:
103
  return base64.b64encode(image_file.read()).decode('utf-8')
104
 
105
+ @lru_cache(maxsize=100) # Cache up to 100 recent analyses
106
+ def analyze_chart(self, image_path: str, persona: str) -> str:
107
+ """Core analysis function with caching and persona-based recommendations"""
108
  try:
109
+ # Optimize image before analysis
110
+ optimized_path = self.optimize_image(image_path)
111
+ base64_image = self.encode_image(optimized_path)
112
+
113
+ # Add persona-specific instructions to the system prompt
114
+ persona_prompt = PERSONAS.get(persona, {}).get("prompt", "")
115
+ full_system_prompt = f"{SYSTEM_PROMPT}\n\n{persona_prompt}"
116
 
117
  response = openai.ChatCompletion.create(
118
  model=ANALYSIS_MODEL,
119
  messages=[
120
  {
121
  "role": "system",
122
+ "content": full_system_prompt
123
  },
124
  {
125
  "role": "user",
 
271
  gr.Markdown("""
272
  <div style="text-align: center; margin-bottom: 32px;">
273
  <h1 style="color: var(--primary-color); font-size: 2.5rem; margin-bottom: 16px;">
274
+ 🚀 CryptoVision Pro
275
  </h1>
276
  <p style="color: var(--text-color); font-size: 1.1rem;">
277
+ Advanced AI-powered cryptocurrency technical analysis
 
 
278
  </p>
279
  </div>
280
  """)
 
291
  sources=["upload"],
292
  height=300
293
  )
294
+ persona_dropdown = gr.Dropdown(
295
+ choices=list(PERSONAS.keys()),
296
+ label="Select Trading Persona",
297
+ value="Neutral Trader"
298
+ )
299
  analyze_btn = gr.Button(
300
  "Analyze Chart",
301
  variant="primary",
 
314
 
315
  # Event Handling
316
  analyze_btn.click(
317
+ fn=lambda: loading_html, # Show loading spinner immediately
318
  outputs=analysis_output,
319
  queue=False
320
  ).then(
321
  fn=analyzer.analyze_chart,
322
+ inputs=[chart_input, persona_dropdown],
323
  outputs=analysis_output,
324
  api_name="analyze"
325
  )