File size: 6,157 Bytes
34fe234
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import os
import base64
import io
import dash
from dash import dcc, html, Input, Output, State
import dash_bootstrap_components as dbc
import pandas as pd
import anthropic
from threading import Thread

# Initialize Dash app
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

# Anthropic API setup
ANTHROPIC_KEY = os.environ.get("ANTHROPIC_API_KEY", "")
anthropic_client = anthropic.Anthropic(api_key=ANTHROPIC_KEY)
CLAUDE3_SONNET_MODEL = "claude-3-7-sonnet-20250219"
CLAUDE3_MAX_CONTEXT_TOKENS = 200_000
CLAUDE3_MAX_OUTPUT_TOKENS = 64_000

# Global variables
uploaded_document = None
shredded_document = None
generated_response = None

# Helper functions
def process_document(content, filename, action):
    global uploaded_document, shredded_document, generated_response
    
    content_type, content_string = content.split(',')
    decoded = base64.b64decode(content_string)
    
    if action == 'upload':
        uploaded_document = io.StringIO(decoded.decode('utf-8')).read()
        return "Document uploaded successfully."
    
    elif action == 'shred':
        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}"
        response = anthropic_client.messages.create(
            model=CLAUDE3_SONNET_MODEL,
            max_tokens=CLAUDE3_MAX_OUTPUT_TOKENS,
            messages=[{"role": "user", "content": prompt}]
        )
        shredded_document = response.content[0].text
        return shredded_document
    
    elif action == 'generate':
        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}"
        response = anthropic_client.messages.create(
            model=CLAUDE3_SONNET_MODEL,
            max_tokens=CLAUDE3_MAX_OUTPUT_TOKENS,
            messages=[{"role": "user", "content": prompt}]
        )
        generated_response = response.content[0].text
        return generated_response
    
    # Implement other actions (check_compliance, recover_document, virtual_board, estimate_loe) similarly

# Layout
app.layout = dbc.Container([
    dbc.Row([
        dbc.Col([
            html.H3("Navigation"),
            dbc.Button("Shred RFP/PWS/SOW/RFI", id="shred-btn", className="mb-2 w-100"),
            dbc.Button("Generate Proposal Response", id="generate-btn", className="mb-2 w-100"),
            dbc.Button("Check Compliance", id="compliance-btn", className="mb-2 w-100"),
            dbc.Button("Recover Document", id="recover-btn", className="mb-2 w-100"),
            dbc.Button("Virtual Board", id="board-btn", className="mb-2 w-100"),
            dbc.Button("Estimate LOE", id="loe-btn", className="mb-2 w-100"),
        ], width=3),
        dbc.Col([
            dbc.Input(id="chat-input", type="text", placeholder="Enter additional instructions..."),
            dbc.Button("Send", id="chat-send-btn", className="mt-2"),
            html.Div([
                dbc.Button("Shred", id="shred-action-btn", className="mr-2"),
                dbc.Button("Generate", id="generate-action-btn", className="mr-2"),
                dbc.Button("Check Compliance", id="compliance-action-btn", className="mr-2"),
                dbc.Button("Recover", id="recover-action-btn", className="mr-2"),
                dbc.Button("Virtual Board", id="board-action-btn", className="mr-2"),
                dbc.Button("LOE", id="loe-action-btn"),
            ], className="mt-3 mb-3"),
            dcc.Upload(
                id='upload-document',
                children=html.Div([
                    'Drag and Drop or ',
                    html.A('Select Files')
                ]),
                style={
                    'width': '100%',
                    'height': '60px',
                    'lineHeight': '60px',
                    'borderWidth': '1px',
                    'borderStyle': 'dashed',
                    'borderRadius': '5px',
                    'textAlign': 'center',
                    'margin': '10px'
                },
                multiple=False
            ),
            html.Div(id='output-document-upload'),
            dcc.Loading(
                id="loading",
                type="default",
                children=html.Div(id="output-data-upload")
            )
        ], width=9)
    ])
], fluid=True)

# Callbacks
@app.callback(
    Output('output-document-upload', 'children'),
    Input('upload-document', 'contents'),
    State('upload-document', 'filename')
)
def update_output(content, filename):
    if content is not None:
        result = process_document(content, filename, 'upload')
        return html.Div(result)

@app.callback(
    Output('output-data-upload', 'children'),
    [Input('shred-action-btn', 'n_clicks'),
     Input('generate-action-btn', 'n_clicks'),
     Input('compliance-action-btn', 'n_clicks'),
     Input('recover-action-btn', 'n_clicks'),
     Input('board-action-btn', 'n_clicks'),
     Input('loe-action-btn', 'n_clicks')],
    State('chat-input', 'value')
)
def update_output(shred_clicks, generate_clicks, compliance_clicks, recover_clicks, board_clicks, loe_clicks, chat_input):
    ctx = dash.callback_context
    if not ctx.triggered:
        return "No action taken yet."
    else:
        button_id = ctx.triggered[0]['prop_id'].split('.')[0]
        if button_id == 'shred-action-btn':
            return process_document(None, None, 'shred')
        elif button_id == 'generate-action-btn':
            return process_document(None, None, 'generate')
        # Implement other actions similarly
    
    return "Action not implemented yet."

if __name__ == '__main__':
    print("Starting the Dash application...")
    app.run(debug=True, host='0.0.0.0', port=7860)
    print("Dash application has finished running.")