KB-Infinity-Tech commited on
Commit
755be98
Β·
verified Β·
1 Parent(s): 2175923

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +186 -30
src/streamlit_app.py CHANGED
@@ -1,40 +1,196 @@
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 pandas as pd
3
+ import numpy as np
4
+ import joblib
5
+
6
+ from pricer import (
7
+ Product,
8
+ suggest_price,
9
+ freshness_factor,
10
+ format_sms,
11
+ simulate_7_days
12
+ )
13
+
14
+ # -----------------------------
15
+ # LOAD TRAINED ML MODEL
16
+ # -----------------------------
17
+ ml_model = joblib.load("demand_model.pkl")
18
+
19
+ def ml_predict(price, age_hours, comp_avg, product_encoded):
20
+ X = pd.DataFrame([[
21
+ price,
22
+ age_hours,
23
+ comp_avg,
24
+ product_encoded
25
+ ]], columns=["price", "age_hours", "comp_avg_price", "product_encoded"])
26
+
27
+ return ml_model.predict(X)[0]
28
+
29
+ # -----------------------------
30
+ # PAGE CONFIG
31
+ # -----------------------------
32
+ st.set_page_config(page_title="AI Hybrid Pricing Engine", layout="wide")
33
+
34
+ st.title("🧠 AI Hybrid Retail Pricing System")
35
+ st.markdown("Rule-based + Machine Learning Dynamic Pricing Engine")
36
+
37
+ # -----------------------------
38
+ # SIDEBAR INPUTS
39
+ # -----------------------------
40
+ st.sidebar.header("πŸ“¦ Product Configuration")
41
+
42
+ sku = st.sidebar.text_input("Product SKU", "TOMATO-A")
43
+ cost = st.sidebar.number_input("Cost (RWF)", 500, 10000, 1000)
44
+ shelf_life = st.sidebar.number_input("Shelf Life (days)", 1, 14, 7)
45
+
46
+ p_ref = st.sidebar.number_input("Reference Price", 1000, 10000, 1800)
47
+ Q0 = st.sidebar.number_input("Base Demand (Q0)", 10, 500, 50)
48
+ alpha = st.sidebar.slider("Price Sensitivity (alpha)", 0.1, 5.0, 1.5)
49
+
50
+ age = st.sidebar.slider("Product Age (days)", 0.0, float(shelf_life), 3.0)
51
+
52
+ # Competitors
53
+ comp1 = st.sidebar.number_input("Competitor 1", 1000, 10000, 1600)
54
+ comp2 = st.sidebar.number_input("Competitor 2", 1000, 10000, 1700)
55
+ comp3 = st.sidebar.number_input("Competitor 3", 1000, 10000, 1900)
56
+
57
+ competitors = [comp1, comp2, comp3]
58
+
59
+ # -----------------------------
60
+ # PRODUCT OBJECT
61
+ # -----------------------------
62
+ product = Product(
63
+ sku=sku,
64
+ cost=cost,
65
+ shelf_life_days=shelf_life,
66
+ p_ref=p_ref,
67
+ Q0=Q0,
68
+ alpha=alpha
69
+ )
70
+
71
+ # -----------------------------
72
+ # RULE-BASED RESULT
73
+ # -----------------------------
74
+ result = suggest_price(product, age, competitors)
75
+
76
+ # -----------------------------
77
+ # DISPLAY METRICS
78
+ # -----------------------------
79
+ col1, col2, col3 = st.columns(3)
80
+
81
+ with col1:
82
+ st.metric("🧊 Freshness", f"{result['freshness']:.3f}")
83
+ st.write(result["freshness_label"])
84
+
85
+ with col2:
86
+ st.metric("πŸ’° Rule Price", f"{result['suggested_price']:.0f} RWF")
87
+
88
+ with col3:
89
+ st.metric("πŸ“ˆ Margin %", f"{result['margin_pct']:.1f}%")
90
+
91
+ st.divider()
92
 
93
+ # -----------------------------
94
+ # SMS OUTPUT
95
+ # -----------------------------
96
+ st.subheader("πŸ“² SMS Output")
97
+ st.code(format_sms(result, "RWF"))
98
 
99
+ # -----------------------------
100
+ # FRESHNESS CURVE
101
+ # -----------------------------
102
+ st.subheader("πŸ“‰ Freshness Decay Curve")
103
 
104
+ days = np.linspace(0, shelf_life, 50)
105
+ values = [freshness_factor(d, shelf_life) for d in days]
106
 
107
+ df_curve = pd.DataFrame({
108
+ "Day": days,
109
+ "Freshness": values
110
+ })
111
 
112
+ st.line_chart(df_curve.set_index("Day"))
 
 
113
 
114
+ # -----------------------------
115
+ # COMPETITOR VIEW
116
+ # -----------------------------
117
+ st.subheader("πŸͺ Market Comparison")
118
 
119
+ df_comp = pd.DataFrame({
120
+ "Entity": ["Competitor 1", "Competitor 2", "Competitor 3", "YOU (Rule)"],
121
+ "Price (RWF)": [comp1, comp2, comp3, result["suggested_price"]]
 
 
122
  })
123
 
124
+ st.dataframe(df_comp)
125
+
126
+ # -----------------------------
127
+ # ML VS RULE COMPARISON
128
+ # -----------------------------
129
+ st.subheader("βš–οΈ Rule Engine vs ML Model")
130
+
131
+ comp_avg = np.mean(competitors)
132
+ product_encoded = 0
133
+
134
+ rule_profit = result["expected_daily_profit"]
135
+
136
+ ml_demand = ml_predict(
137
+ result["suggested_price"],
138
+ age * 24,
139
+ comp_avg,
140
+ product_encoded
141
+ )
142
+
143
+ ml_profit = (result["suggested_price"] - cost) * ml_demand
144
+
145
+ col1, col2 = st.columns(2)
146
+
147
+ with col1:
148
+ st.metric("πŸ“ Rule Profit", f"{rule_profit:.2f} RWF")
149
+
150
+ with col2:
151
+ st.metric("πŸ€– ML Profit", f"{ml_profit:.2f} RWF")
152
+
153
+ # -----------------------------
154
+ # PROFIT CURVE COMPARISON
155
+ # -----------------------------
156
+ st.subheader("πŸ“Š Profit Curve Comparison")
157
+
158
+ prices = np.linspace(500, 5000, 30)
159
+
160
+ ml_profits = []
161
+ rule_profits = []
162
+
163
+ for p in prices:
164
+ ml_d = ml_predict(p, age * 24, comp_avg, product_encoded)
165
+ ml_profits.append((p - cost) * ml_d)
166
+
167
+ rule_profits.append(result["expected_daily_profit"])
168
+
169
+ df_compare = pd.DataFrame({
170
+ "Price": prices,
171
+ "ML_Profit": ml_profits,
172
+ "Rule_Profit": rule_profits
173
+ })
174
+
175
+ st.line_chart(df_compare.set_index("Price"))
176
+
177
+ # -----------------------------
178
+ # 7-DAY SIMULATION
179
+ # -----------------------------
180
+ st.subheader("πŸ“Š 7-Day Simulation")
181
+
182
+ if st.button("Run Simulation"):
183
+
184
+ sim = simulate_7_days(product, competitors)
185
+ df_sim = pd.DataFrame(sim)
186
+
187
+ if "day" in df_sim.columns:
188
+ st.line_chart(df_sim.set_index("day")[["our_price", "demand"]])
189
+
190
+ st.dataframe(df_sim)
191
+
192
+ # -----------------------------
193
+ # FOOTER
194
+ # -----------------------------
195
+ st.markdown("---")
196
+ st.markdown("⚑ Hybrid AI Pricing System β€” Rule Engine + Machine Learning | AIMS-RIC Hackathon")