bluenevus commited on
Commit
3f68dbe
·
verified ·
1 Parent(s): 6654f6c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +189 -0
app.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import io
3
+ import base64
4
+ import threading
5
+ import logging
6
+ from dash import Dash, dcc, html, Input, Output, State
7
+ import dash_bootstrap_components as dbc
8
+ import openai
9
+ from google import generativeai as genai
10
+ from anthropic import Anthropic
11
+ import requests
12
+ from diagrams import Diagram, Cluster
13
+ from diagrams.aws.compute import EC2
14
+ from diagrams.aws.database import RDS
15
+ from diagrams.aws.network import ELB
16
+ from diagrams.gcp.compute import ComputeEngine
17
+ from diagrams.gcp.database import SQL
18
+ from diagrams.gcp.network import LoadBalancing
19
+ from diagrams.onprem.compute import Server
20
+ from diagrams.onprem.database import PostgreSQL
21
+ from diagrams.onprem.network import Nginx
22
+
23
+ # Configure logging
24
+ logging.basicConfig(level=logging.INFO)
25
+
26
+ # Initialize API clients
27
+ openai.api_key = os.getenv("OPENAI_API_KEY")
28
+ if not openai.api_key:
29
+ logging.warning("OPENAI_API_KEY not set. GPT-3.5 model will not be available.")
30
+
31
+ google_api_key = os.getenv("GOOGLE_API_KEY")
32
+ if google_api_key:
33
+ try:
34
+ genai.configure(api_key=google_api_key)
35
+ except Exception as e:
36
+ logging.error(f"Failed to configure Google Gemini: {e}")
37
+ genai = None
38
+ else:
39
+ genai = None
40
+ logging.warning("GOOGLE_API_KEY not set. Gemini model will not be available.")
41
+
42
+ anthropic_api_key = os.getenv("ANTHROPIC_API_KEY")
43
+ if anthropic_api_key:
44
+ try:
45
+ anthropic = Anthropic(api_key=anthropic_api_key)
46
+ except Exception as e:
47
+ logging.error(f"Failed to initialize Anthropic client: {e}")
48
+ anthropic = None
49
+ else:
50
+ anthropic = None
51
+ logging.warning("ANTHROPIC_API_KEY not set. Claude model will not be available.")
52
+
53
+ grok_api_key = os.getenv("GROK_API_KEY")
54
+ if not grok_api_key:
55
+ logging.warning("GROK_API_KEY not set. Groq model will not be available.")
56
+
57
+ app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
58
+
59
+ # Global variable to store the generated diagram
60
+ generated_diagram = None
61
+
62
+ def generate_diagram(description):
63
+ global generated_diagram
64
+ # This is a placeholder function. In a real implementation, you would parse the AI model's
65
+ # output and create a diagram based on that. For now, we'll create a simple diagram.
66
+ with Diagram("Architecture", show=False) as diag:
67
+ with Cluster("Cloud"):
68
+ lb = ELB("Load Balancer")
69
+ with Cluster("Web Tier"):
70
+ web = [EC2("Web Server 1"),
71
+ EC2("Web Server 2")]
72
+ with Cluster("Database Tier"):
73
+ db_master = RDS("Master")
74
+ db_slave = RDS("Slave")
75
+
76
+ lb >> web
77
+ web >> db_master
78
+ db_master - db_slave
79
+
80
+ img_bytes = diag.dot.pipe(format='png')
81
+ generated_diagram = base64.b64encode(img_bytes).decode('utf-8')
82
+ return generated_diagram
83
+
84
+ def get_ai_response(model, prompt):
85
+ if model == 'gpt-3.5-turbo':
86
+ response = openai.ChatCompletion.create(
87
+ model="gpt-3.5-turbo",
88
+ messages=[{"role": "user", "content": prompt}]
89
+ )
90
+ return response.choices[0].message.content
91
+ elif model == 'gemini-1.5-flash-latest':
92
+ model = genai.GenerativeModel('gemini-1.5-pro')
93
+ response = model.generate_content(prompt)
94
+ return response.text
95
+ elif model == 'claude-3-5-haiku-20241022':
96
+ response = anthropic.messages.create(
97
+ model="claude-3-5-haiku-20241022",
98
+ max_tokens=2000,
99
+ messages=[{"role": "user", "content": prompt}]
100
+ )
101
+ return response.content[0].text
102
+ elif model == 'grok-3-mini-fast-beta':
103
+ groq_url = "https://api.groq.com/openai/v1/chat/completions"
104
+ headers = {
105
+ "Authorization": f"Bearer {grok_api_key}",
106
+ "Content-Type": "application/json"
107
+ }
108
+ data = {
109
+ "model": "grok-3-mini-fast-beta",
110
+ "messages": [{"role": "user", "content": prompt}]
111
+ }
112
+ response = requests.post(groq_url, json=data, headers=headers)
113
+ return response.json()['choices'][0]['message']['content']
114
+ else:
115
+ return "Error: Invalid model selected."
116
+
117
+ app.layout = dbc.Container([
118
+ html.H1("Architecture Diagram Generator", className="my-4"),
119
+ dbc.Row([
120
+ dbc.Col([
121
+ dcc.Dropdown(
122
+ id='model-dropdown',
123
+ options=[
124
+ {'label': 'GPT-3.5 Turbo', 'value': 'gpt-3.5-turbo'},
125
+ {'label': 'Gemini 1.5 Flash', 'value': 'gemini-1.5-flash-latest'},
126
+ {'label': 'Claude 3.5 Haiku', 'value': 'claude-3-5-haiku-20241022'},
127
+ {'label': 'Grok 3 Mini Fast', 'value': 'grok-3-mini-fast-beta'}
128
+ ],
129
+ value='gpt-3.5-turbo',
130
+ className="mb-3"
131
+ ),
132
+ dbc.Textarea(id='description-input', placeholder="Enter architecture description here...", style={'height': '200px'}, className="mb-3"),
133
+ dbc.Button("Generate Diagram", id='generate-button', color="primary", className="mb-3"),
134
+ dbc.Button("Download Diagram", id='download-button', color="secondary", className="mb-3", disabled=True),
135
+ dcc.Download(id="download-diagram"),
136
+ html.Div(id='status-message', className="mb-3")
137
+ ], width=4),
138
+ dbc.Col([
139
+ html.Img(id='diagram-output', style={'width': '100%'})
140
+ ], width=8)
141
+ ])
142
+ ], fluid=True)
143
+
144
+ @app.callback(
145
+ [Output('diagram-output', 'src'),
146
+ Output('status-message', 'children'),
147
+ Output('download-button', 'disabled')],
148
+ [Input('generate-button', 'n_clicks')],
149
+ [State('description-input', 'value'),
150
+ State('model-dropdown', 'value')],
151
+ prevent_initial_call=True
152
+ )
153
+ def update_diagram(n_clicks, description, model):
154
+ if n_clicks is None:
155
+ return dash.no_update, dash.no_update, True
156
+
157
+ if not description:
158
+ return dash.no_update, "Please enter a description.", True
159
+
160
+ try:
161
+ # Get AI response
162
+ ai_response = get_ai_response(model, description)
163
+
164
+ # Generate diagram based on AI response
165
+ diagram_base64 = generate_diagram(ai_response)
166
+
167
+ return f'data:image/png;base64,{diagram_base64}', "Diagram generated successfully!", False
168
+ except Exception as e:
169
+ logging.error(f"Error generating diagram: {str(e)}")
170
+ return dash.no_update, f"Error: {str(e)}", True
171
+
172
+ @app.callback(
173
+ Output("download-diagram", "data"),
174
+ Input("download-button", "n_clicks"),
175
+ prevent_initial_call=True
176
+ )
177
+ def download_diagram(n_clicks):
178
+ if n_clicks is None:
179
+ return dash.no_update
180
+
181
+ if generated_diagram is None:
182
+ return dash.no_update
183
+
184
+ return dcc.send_bytes(base64.b64decode(generated_diagram), "architecture_diagram.png")
185
+
186
+ if __name__ == '__main__':
187
+ print("Starting the Dash application...")
188
+ app.run(debug=True, host='0.0.0.0', port=7860)
189
+ print("Dash application has finished running.")