Spaces:
Paused
Paused
Update app.py via AI Editor
Browse files
app.py
CHANGED
@@ -1 +1,148 @@
|
|
1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import base64
|
3 |
+
import io
|
4 |
+
import dash
|
5 |
+
from dash import dcc, html, Input, Output, State
|
6 |
+
import dash_bootstrap_components as dbc
|
7 |
+
import pandas as pd
|
8 |
+
import anthropic
|
9 |
+
from threading import Thread
|
10 |
+
|
11 |
+
# Initialize Dash app
|
12 |
+
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
|
13 |
+
|
14 |
+
# Anthropic API setup
|
15 |
+
ANTHROPIC_KEY = os.environ.get("ANTHROPIC_API_KEY", "")
|
16 |
+
anthropic_client = anthropic.Anthropic(api_key=ANTHROPIC_KEY)
|
17 |
+
CLAUDE3_SONNET_MODEL = "claude-3-7-sonnet-20250219"
|
18 |
+
CLAUDE3_MAX_CONTEXT_TOKENS = 200_000
|
19 |
+
CLAUDE3_MAX_OUTPUT_TOKENS = 64_000
|
20 |
+
|
21 |
+
# Global variables
|
22 |
+
uploaded_document = None
|
23 |
+
shredded_document = None
|
24 |
+
generated_response = None
|
25 |
+
|
26 |
+
# Helper functions
|
27 |
+
def process_document(content, filename, action):
|
28 |
+
global uploaded_document, shredded_document, generated_response
|
29 |
+
|
30 |
+
content_type, content_string = content.split(',')
|
31 |
+
decoded = base64.b64decode(content_string)
|
32 |
+
|
33 |
+
if action == 'upload':
|
34 |
+
uploaded_document = io.StringIO(decoded.decode('utf-8')).read()
|
35 |
+
return "Document uploaded successfully."
|
36 |
+
|
37 |
+
elif action == 'shred':
|
38 |
+
prompt = f"Analyze the following RFP/PWS/SOW/RFI and generate a requirements spreadsheet. Identify requirements by action words like 'shall', 'will', 'perform', etc. Organize by PWS section and requirement. Do not write as if responding to the proposal:\n\n{uploaded_document}"
|
39 |
+
response = anthropic_client.messages.create(
|
40 |
+
model=CLAUDE3_SONNET_MODEL,
|
41 |
+
max_tokens=CLAUDE3_MAX_OUTPUT_TOKENS,
|
42 |
+
messages=[{"role": "user", "content": prompt}]
|
43 |
+
)
|
44 |
+
shredded_document = response.content[0].text
|
45 |
+
return shredded_document
|
46 |
+
|
47 |
+
elif action == 'generate':
|
48 |
+
prompt = f"Create a highly detailed proposal response based on the following PWS requirements. Be compliant and compelling. Focus on describing the approach, steps, workflow, people, processes, and technology. Refer to research that validates the approach and cite sources with measurable outcomes:\n\n{shredded_document}"
|
49 |
+
response = anthropic_client.messages.create(
|
50 |
+
model=CLAUDE3_SONNET_MODEL,
|
51 |
+
max_tokens=CLAUDE3_MAX_OUTPUT_TOKENS,
|
52 |
+
messages=[{"role": "user", "content": prompt}]
|
53 |
+
)
|
54 |
+
generated_response = response.content[0].text
|
55 |
+
return generated_response
|
56 |
+
|
57 |
+
# Implement other actions (check_compliance, recover_document, virtual_board, estimate_loe) similarly
|
58 |
+
|
59 |
+
# Layout
|
60 |
+
app.layout = dbc.Container([
|
61 |
+
dbc.Row([
|
62 |
+
dbc.Col([
|
63 |
+
html.H3("Navigation"),
|
64 |
+
dbc.Button("Shred RFP/PWS/SOW/RFI", id="shred-btn", className="mb-2 w-100"),
|
65 |
+
dbc.Button("Generate Proposal Response", id="generate-btn", className="mb-2 w-100"),
|
66 |
+
dbc.Button("Check Compliance", id="compliance-btn", className="mb-2 w-100"),
|
67 |
+
dbc.Button("Recover Document", id="recover-btn", className="mb-2 w-100"),
|
68 |
+
dbc.Button("Virtual Board", id="board-btn", className="mb-2 w-100"),
|
69 |
+
dbc.Button("Estimate LOE", id="loe-btn", className="mb-2 w-100"),
|
70 |
+
], width=3),
|
71 |
+
dbc.Col([
|
72 |
+
dbc.Input(id="chat-input", type="text", placeholder="Enter additional instructions..."),
|
73 |
+
dbc.Button("Send", id="chat-send-btn", className="mt-2"),
|
74 |
+
html.Div([
|
75 |
+
dbc.Button("Shred", id="shred-action-btn", className="mr-2"),
|
76 |
+
dbc.Button("Generate", id="generate-action-btn", className="mr-2"),
|
77 |
+
dbc.Button("Check Compliance", id="compliance-action-btn", className="mr-2"),
|
78 |
+
dbc.Button("Recover", id="recover-action-btn", className="mr-2"),
|
79 |
+
dbc.Button("Virtual Board", id="board-action-btn", className="mr-2"),
|
80 |
+
dbc.Button("LOE", id="loe-action-btn"),
|
81 |
+
], className="mt-3 mb-3"),
|
82 |
+
dcc.Upload(
|
83 |
+
id='upload-document',
|
84 |
+
children=html.Div([
|
85 |
+
'Drag and Drop or ',
|
86 |
+
html.A('Select Files')
|
87 |
+
]),
|
88 |
+
style={
|
89 |
+
'width': '100%',
|
90 |
+
'height': '60px',
|
91 |
+
'lineHeight': '60px',
|
92 |
+
'borderWidth': '1px',
|
93 |
+
'borderStyle': 'dashed',
|
94 |
+
'borderRadius': '5px',
|
95 |
+
'textAlign': 'center',
|
96 |
+
'margin': '10px'
|
97 |
+
},
|
98 |
+
multiple=False
|
99 |
+
),
|
100 |
+
html.Div(id='output-document-upload'),
|
101 |
+
dcc.Loading(
|
102 |
+
id="loading",
|
103 |
+
type="default",
|
104 |
+
children=html.Div(id="output-data-upload")
|
105 |
+
)
|
106 |
+
], width=9)
|
107 |
+
])
|
108 |
+
], fluid=True)
|
109 |
+
|
110 |
+
# Callbacks
|
111 |
+
@app.callback(
|
112 |
+
Output('output-document-upload', 'children'),
|
113 |
+
Input('upload-document', 'contents'),
|
114 |
+
State('upload-document', 'filename')
|
115 |
+
)
|
116 |
+
def update_output(content, filename):
|
117 |
+
if content is not None:
|
118 |
+
result = process_document(content, filename, 'upload')
|
119 |
+
return html.Div(result)
|
120 |
+
|
121 |
+
@app.callback(
|
122 |
+
Output('output-data-upload', 'children'),
|
123 |
+
[Input('shred-action-btn', 'n_clicks'),
|
124 |
+
Input('generate-action-btn', 'n_clicks'),
|
125 |
+
Input('compliance-action-btn', 'n_clicks'),
|
126 |
+
Input('recover-action-btn', 'n_clicks'),
|
127 |
+
Input('board-action-btn', 'n_clicks'),
|
128 |
+
Input('loe-action-btn', 'n_clicks')],
|
129 |
+
State('chat-input', 'value')
|
130 |
+
)
|
131 |
+
def update_output(shred_clicks, generate_clicks, compliance_clicks, recover_clicks, board_clicks, loe_clicks, chat_input):
|
132 |
+
ctx = dash.callback_context
|
133 |
+
if not ctx.triggered:
|
134 |
+
return "No action taken yet."
|
135 |
+
else:
|
136 |
+
button_id = ctx.triggered[0]['prop_id'].split('.')[0]
|
137 |
+
if button_id == 'shred-action-btn':
|
138 |
+
return process_document(None, None, 'shred')
|
139 |
+
elif button_id == 'generate-action-btn':
|
140 |
+
return process_document(None, None, 'generate')
|
141 |
+
# Implement other actions similarly
|
142 |
+
|
143 |
+
return "Action not implemented yet."
|
144 |
+
|
145 |
+
if __name__ == '__main__':
|
146 |
+
print("Starting the Dash application...")
|
147 |
+
app.run(debug=True, host='0.0.0.0', port=7860)
|
148 |
+
print("Dash application has finished running.")
|