PD03 commited on
Commit
a3a7ce5
Β·
verified Β·
1 Parent(s): ee6e12d

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +320 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,322 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
+ import os
3
+ from smolagents import CodeAgent, LiteLLMModel, tool
4
+ import json
5
+ from datetime import datetime
6
+ import random
7
 
8
+ # Hugging Face Spaces configuration
9
+ st.set_page_config(
10
+ page_title="AI Procurement Agent",
11
+ page_icon="πŸ€–",
12
+ layout="wide"
13
+ )
14
+
15
+ # Initialize OpenAI model for Spaces
16
+ @st.cache_resource
17
+ def get_model():
18
+ # Try to get API key from Spaces secrets or environment
19
+ api_key = os.environ.get("OPENAI_API_KEY")
20
+ if not api_key:
21
+ st.error("⚠️ OpenAI API Key not found in Spaces secrets!")
22
+ st.info("Add OPENAI_API_KEY to your Spaces secrets in Settings.")
23
+ st.stop()
24
+
25
+ return LiteLLMModel(
26
+ model_id="gpt-4",
27
+ api_key=api_key,
28
+ temperature=0.2
29
+ )
30
+
31
+ # Tool 1: Query SAP Purchase Requisition
32
+ @tool
33
+ def query_sap_pr(pr_number: str) -> str:
34
+ """Query SAP purchase requisition details"""
35
+ materials = ["Steel Pipes", "Cement", "Electrical Cables", "Safety Equipment"]
36
+ mock_data = {
37
+ "pr_number": pr_number,
38
+ "materials": f"{random.choice(materials)} - {random.randint(50, 200)} units",
39
+ "total_value": random.randint(30000, 80000),
40
+ "requestor": random.choice(["John Doe", "Jane Smith", "Mike Johnson"]),
41
+ "department": random.choice(["Construction", "Manufacturing", "Maintenance"]),
42
+ "urgency": random.choice(["High", "Medium", "Low"]),
43
+ "delivery_date": "2025-10-15",
44
+ "status": "Approved"
45
+ }
46
+ return json.dumps(mock_data, indent=2)
47
+
48
+ # Tool 2: Check Vendor Financial Health
49
+ @tool
50
+ def check_vendor_solvency(vendor_name: str) -> str:
51
+ """Check vendor financial solvency from external sources"""
52
+ scores = ["A+", "A", "A-", "B+", "B"]
53
+ risk_levels = ["Low", "Medium", "High"]
54
+ mock_data = {
55
+ "vendor_name": vendor_name,
56
+ "credit_rating": random.choice(scores),
57
+ "financial_stability": "Stable",
58
+ "solvency_score": random.randint(65, 95),
59
+ "debt_ratio": round(random.uniform(0.2, 0.6), 2),
60
+ "risk_level": random.choice(risk_levels[:2]), # Mostly Low/Medium
61
+ "recommendation": "Approved for business"
62
+ }
63
+ return json.dumps(mock_data, indent=2)
64
+
65
+ # Tool 3: Get Vendor Performance History
66
+ @tool
67
+ def get_vendor_performance(vendor_name: str) -> str:
68
+ """Get historical vendor performance metrics"""
69
+ mock_data = {
70
+ "vendor_name": vendor_name,
71
+ "evaluation_period": "12 months",
72
+ "total_orders": random.randint(15, 80),
73
+ "on_time_delivery": f"{random.randint(85, 98)}%",
74
+ "quality_score": round(random.uniform(3.5, 5.0), 1),
75
+ "order_accuracy": f"{random.randint(92, 99)}%",
76
+ "avg_lead_time": f"{random.randint(7, 21)} days",
77
+ "overall_rating": round(random.uniform(3.5, 4.8), 1),
78
+ "issues_resolved": random.randint(0, 3)
79
+ }
80
+ return json.dumps(mock_data, indent=2)
81
+
82
+ # Tool 4: Compare Material Rates
83
+ @tool
84
+ def compare_material_rates(material: str) -> str:
85
+ """Compare current market rates for materials"""
86
+ vendors = ["Alpha Corp", "Beta Supplies", "Gamma Materials", "Delta Industries"]
87
+ base_price = random.randint(80, 250)
88
+
89
+ quotes = []
90
+ for vendor in random.sample(vendors, 3):
91
+ quotes.append({
92
+ "vendor": vendor,
93
+ "price_per_unit": base_price + random.randint(-25, 30),
94
+ "lead_time": f"{random.randint(5, 20)} days",
95
+ "min_order": random.randint(10, 50)
96
+ })
97
+
98
+ mock_data = {
99
+ "material": material,
100
+ "market_average": base_price,
101
+ "vendor_quotes": quotes,
102
+ "best_value_vendor": min(quotes, key=lambda x: x["price_per_unit"])["vendor"],
103
+ "price_trend": random.choice(["Stable", "Increasing", "Decreasing"])
104
+ }
105
+ return json.dumps(mock_data, indent=2)
106
+
107
+ # Tool 5: Optimize Vendor Selection
108
+ @tool
109
+ def optimize_vendor_selection(requirements: str) -> str:
110
+ """Run optimization to find best vendor combination"""
111
+ vendors = ["ABC Supplies", "XYZ Materials", "DEF Corp", "GHI Industries"]
112
+ selected_vendor = random.choice(vendors)
113
+
114
+ mock_data = {
115
+ "requirements_analyzed": requirements,
116
+ "recommended_vendor": selected_vendor,
117
+ "optimization_score": round(random.uniform(7.5, 9.5), 1),
118
+ "total_estimated_cost": random.randint(40000, 70000),
119
+ "potential_savings": f"{random.randint(8, 18)}%",
120
+ "risk_assessment": "Low to Medium",
121
+ "confidence_level": f"{random.randint(85, 96)}%",
122
+ "key_factors": ["Cost efficiency", "Quality track record", "Delivery reliability"]
123
+ }
124
+ return json.dumps(mock_data, indent=2)
125
+
126
+ # Tool 6: Create SAP Purchase Order
127
+ @tool
128
+ def create_purchase_order(vendor: str, amount: str) -> str:
129
+ """Create purchase order in SAP system"""
130
+ po_number = f"PO{datetime.now().strftime('%Y%m%d%H%M%S')[-8:]}"
131
+
132
+ mock_data = {
133
+ "po_number": po_number,
134
+ "vendor": vendor,
135
+ "total_amount": amount,
136
+ "currency": "USD",
137
+ "status": "Created Successfully",
138
+ "payment_terms": "NET 30",
139
+ "delivery_terms": "FOB Destination",
140
+ "created_by": "AI_Procurement_Agent",
141
+ "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
142
+ "approval_required": random.choice([True, False])
143
+ }
144
+ return json.dumps(mock_data, indent=2)
145
+
146
+ # Initialize Agent
147
+ @st.cache_resource
148
+ def get_agent():
149
+ tools = [
150
+ query_sap_pr,
151
+ check_vendor_solvency,
152
+ get_vendor_performance,
153
+ compare_material_rates,
154
+ optimize_vendor_selection,
155
+ create_purchase_order
156
+ ]
157
+
158
+ return CodeAgent(
159
+ tools=tools,
160
+ model=get_model(),
161
+ max_iterations=8
162
+ )
163
+
164
+ def main():
165
+ # Header
166
+ st.title("πŸ€– AI Procurement Agent")
167
+ st.markdown("*Demo powered by Hugging Face SmolAgents + OpenAI GPT-4*")
168
+
169
+ # Add info about the demo
170
+ with st.expander("ℹ️ About this Demo"):
171
+ st.markdown("""
172
+ This AI agent can help automate procurement workflows by:
173
+ - Querying purchase requisitions
174
+ - Evaluating vendor financial health
175
+ - Analyzing vendor performance history
176
+ - Comparing material market rates
177
+ - Optimizing vendor selection
178
+ - Creating purchase orders
179
+
180
+ **Note:** This uses mock data for demonstration purposes.
181
+ """)
182
+
183
+ # Sidebar
184
+ with st.sidebar:
185
+ st.header("🎯 Demo Scenarios")
186
+ scenario = st.selectbox(
187
+ "Choose a workflow:",
188
+ [
189
+ "πŸ”„ Full Procurement Workflow",
190
+ "πŸ“Š Vendor Evaluation",
191
+ "πŸ’° Price Analysis",
192
+ "πŸ€– Custom AI Query"
193
+ ]
194
+ )
195
+
196
+ st.markdown("---")
197
+ st.markdown("**πŸš€ Deployed on Hugging Face Spaces**")
198
+
199
+ # Main content
200
+ col1, col2 = st.columns([1, 1])
201
+
202
+ with col1:
203
+ st.header("πŸ“ Input")
204
+
205
+ if scenario == "πŸ”„ Full Procurement Workflow":
206
+ pr_number = st.text_input("Enter PR Number:", value="PR-2025-001")
207
+
208
+ if st.button("πŸš€ Start Full Workflow", type="primary", use_container_width=True):
209
+ process_full_workflow(pr_number)
210
+
211
+ elif scenario == "πŸ“Š Vendor Evaluation":
212
+ vendor_name = st.text_input("Enter Vendor Name:", value="ABC Supplies")
213
+
214
+ if st.button("πŸ“Š Evaluate This Vendor", use_container_width=True):
215
+ evaluate_vendor(vendor_name)
216
+
217
+ elif scenario == "πŸ’° Price Analysis":
218
+ material = st.text_input("Enter Material Type:", value="Steel Pipes")
219
+
220
+ if st.button("πŸ’° Analyze Market Prices", use_container_width=True):
221
+ analyze_prices(material)
222
+
223
+ else: # Custom Query
224
+ custom_query = st.text_area(
225
+ "Enter your procurement query:",
226
+ value="Evaluate vendor XYZ Corp and check if they're suitable for a 50K USD steel pipes order",
227
+ height=80
228
+ )
229
+
230
+ if st.button("πŸ€– Ask AI Agent", use_container_width=True):
231
+ run_custom_query(custom_query)
232
+
233
+ with col2:
234
+ st.header("πŸ€– AI Agent Response")
235
+
236
+ if 'agent_response' not in st.session_state:
237
+ st.info("πŸ‘ˆ Select a scenario and click a button to see the AI agent in action!")
238
+ else:
239
+ with st.container():
240
+ st.success("βœ… Agent completed successfully!")
241
+
242
+ # Display response in an expandable section
243
+ with st.expander("πŸ“‹ Full Agent Response", expanded=True):
244
+ st.markdown(st.session_state['agent_response'])
245
+
246
+ def process_full_workflow(pr_number):
247
+ """Process complete procurement workflow"""
248
+ with st.spinner("πŸ€– AI Agent is working on your procurement request..."):
249
+ prompt = f"""
250
+ Execute a complete procurement workflow for PR {pr_number}:
251
+
252
+ 1. Query the SAP purchase requisition details
253
+ 2. For any vendors found, check their financial solvency
254
+ 3. Review their historical performance
255
+ 4. Compare current market rates for the materials
256
+ 5. Run optimization to select the best vendor option
257
+ 6. Create a purchase order for the recommended vendor
258
+
259
+ Provide a clear summary with your final recommendation and reasoning.
260
+ """
261
+
262
+ try:
263
+ agent = get_agent()
264
+ result = agent.run(prompt)
265
+ st.session_state['agent_response'] = result
266
+ st.rerun()
267
+ except Exception as e:
268
+ st.error(f"Error: {str(e)}")
269
+
270
+ def evaluate_vendor(vendor_name):
271
+ """Evaluate specific vendor"""
272
+ with st.spinner(f"πŸ€– Evaluating {vendor_name}..."):
273
+ prompt = f"""
274
+ Conduct a comprehensive evaluation of vendor '{vendor_name}':
275
+
276
+ 1. Check their financial solvency and credit rating
277
+ 2. Analyze their historical performance metrics
278
+ 3. Provide a clear recommendation on working with them
279
+ 4. Highlight any risks or benefits
280
+ """
281
+
282
+ try:
283
+ agent = get_agent()
284
+ result = agent.run(prompt)
285
+ st.session_state['agent_response'] = result
286
+ st.rerun()
287
+ except Exception as e:
288
+ st.error(f"Error: {str(e)}")
289
+
290
+ def analyze_prices(material):
291
+ """Analyze material prices"""
292
+ with st.spinner(f"πŸ€– Analyzing prices for {material}..."):
293
+ prompt = f"""
294
+ Perform price analysis for '{material}':
295
+
296
+ 1. Get current market rates from multiple vendors
297
+ 2. Compare pricing and identify the best value option
298
+ 3. Consider factors like lead time and minimum orders
299
+ 4. Provide pricing recommendations
300
+ """
301
+
302
+ try:
303
+ agent = get_agent()
304
+ result = agent.run(prompt)
305
+ st.session_state['agent_response'] = result
306
+ st.rerun()
307
+ except Exception as e:
308
+ st.error(f"Error: {str(e)}")
309
+
310
+ def run_custom_query(query):
311
+ """Run custom user query"""
312
+ with st.spinner("πŸ€– Processing your custom query..."):
313
+ try:
314
+ agent = get_agent()
315
+ result = agent.run(query)
316
+ st.session_state['agent_response'] = result
317
+ st.rerun()
318
+ except Exception as e:
319
+ st.error(f"Error: {str(e)}")
320
+
321
+ if __name__ == "__main__":
322
+ main()