ecopus commited on
Commit
575ccf3
·
verified ·
1 Parent(s): 43f531c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +109 -7
app.py CHANGED
@@ -79,13 +79,115 @@ tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
79
  pipe = pipeline("text-generation", model=MODEL_ID, tokenizer=tokenizer)
80
 
81
  def llm_explain(record: dict) -> str:
82
- if not record.get("ok", False):
83
- return "Errors: " + "; ".join(record.get("errors", []))
84
- comp = record["computed"]
85
- inter = record["intermediate"]
86
- Re_avg = (inter["Re1"] + inter["Re2"]) / 2
87
- regime = "laminar" if Re_avg < 2300 else "turbulent"
88
- return f"Pump head {comp['pump_head']:.3f} m, f={inter['friction_factor']:.4f}, h_f={inter['head_loss']:.3f} m. Flow regime: {regime}."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
  def compute_and_explain(P1,P2,V1,V2,z1,z2,rho,mu,D,L,roughness,use_darcy,mode):
91
  record = bernoulli_pipe_flow(P1,P2,V1,V2,z1,z2,rho,mu,roughness,D,L,None,use_darcy)
 
79
  pipe = pipeline("text-generation", model=MODEL_ID, tokenizer=tokenizer)
80
 
81
  def llm_explain(record: dict) -> str:
82
+ """
83
+ Grounded interpretation of the numeric results in `record`.
84
+ - No added facts beyond the numeric values present in `record`.
85
+ - No long tangents — only short, actionable interpretation.
86
+ """
87
+ if not isinstance(record, dict):
88
+ return "No numeric record provided."
89
+
90
+ if not record.get("ok", True):
91
+ return "Errors: " + "; ".join(record.get("errors", ["unknown error"]))
92
+
93
+ inter = record.get("intermediate", {}) or {}
94
+ comp = record.get("computed", {}) or {}
95
+
96
+ # helper: search for first available key in a dict
97
+ def find_first(d, keys):
98
+ for k in keys:
99
+ if k in d and d[k] is not None:
100
+ return d[k]
101
+ return None
102
+
103
+ # Pump head: try several likely keys
104
+ pump_head = find_first(comp, ["pump_head_required_m", "pump_head", "pump_head_m", "pump_head_required"])
105
+ # Head loss (Darcy-Weisbach)
106
+ h_f = find_first(inter, ["head_loss_hf_m", "head_loss", "head_loss_m", "head_loss_hf"])
107
+ # friction factor
108
+ f = find_first(inter, ["friction_factor_f", "friction_factor", "f"])
109
+ # Reynolds numbers
110
+ Re1 = find_first(inter, ["Re1", "re1"])
111
+ Re2 = find_first(inter, ["Re2", "re2"])
112
+
113
+ # convert to floats where possible
114
+ def as_float(x):
115
+ try:
116
+ return float(x)
117
+ except Exception:
118
+ return None
119
+
120
+ pump_head = as_float(pump_head)
121
+ h_f = as_float(h_f)
122
+ f = as_float(f)
123
+ Re1 = as_float(Re1)
124
+ Re2 = as_float(Re2)
125
+
126
+ # compute average Re and regime if possible
127
+ Re_avg = None
128
+ if (Re1 is not None) and (Re2 is not None):
129
+ Re_avg = (Re1 + Re2) / 2.0
130
+
131
+ if Re_avg is not None:
132
+ regime = "laminar" if Re_avg < 2300 else "turbulent"
133
+ else:
134
+ regime = "unknown"
135
+
136
+ parts = []
137
+
138
+ # 1) Short numeric summary (always the first sentence if any data exists)
139
+ summary_items = []
140
+ if pump_head is not None:
141
+ summary_items.append(f"pump head = {pump_head:.3f} m")
142
+ if h_f is not None:
143
+ summary_items.append(f"head loss = {h_f:.3f} m")
144
+ if f is not None:
145
+ summary_items.append(f"friction factor f = {f:.4f}")
146
+ if (Re1 is not None) and (Re2 is not None):
147
+ summary_items.append(f"Re1 = {int(Re1)}, Re2 = {int(Re2)} ({regime})")
148
+
149
+ if summary_items:
150
+ parts.append(". ".join(summary_items) + ".")
151
+
152
+ # 2) Direct interpretation comparing pump head and head loss
153
+ if (pump_head is not None) and (h_f is not None):
154
+ # tolerance: treat values within 1e-2 m or 1% as "approximately equal"
155
+ tol = max(1e-2, 0.01 * max(abs(pump_head), abs(h_f), 1.0))
156
+ diff = pump_head - h_f
157
+ if abs(diff) <= tol:
158
+ parts.append(
159
+ "Interpretation: pump head and frictional head loss are approximately equal, "
160
+ "so the system is near equilibrium (no net head gain)."
161
+ )
162
+ elif diff > 0:
163
+ parts.append(
164
+ f"Interpretation: pump head exceeds head loss by {diff:.3f} m — the pump can overcome frictional losses and provide net head to the system."
165
+ )
166
+ else:
167
+ parts.append(
168
+ f"Interpretation: pump head is lower than head loss by {abs(diff):.3f} m — the pump cannot fully overcome the frictional losses under these conditions."
169
+ )
170
+ else:
171
+ parts.append("Interpretation: insufficient data to directly compare pump head and head loss.")
172
+
173
+ # 3) Flow regime and friction factor context (concise and factual)
174
+ if regime != "unknown":
175
+ parts.append(f"Flow regime: {regime}.")
176
+ if f is not None:
177
+ parts.append("Friction factor was estimated (value shown above).")
178
+
179
+ # 4) Short, practical note (no speculation)
180
+ parts.append(
181
+ "Notes: the friction factor in this calculation is estimated numerically (Haaland approximation for turbulent flow); "
182
+ "these results are for preliminary assessment and assume steady, incompressible flow."
183
+ )
184
+
185
+ # Final safe fallback
186
+ explanation = " ".join(parts).strip()
187
+ if not explanation:
188
+ explanation = "No explanation could be generated from the provided record."
189
+ return explanation
190
+
191
 
192
  def compute_and_explain(P1,P2,V1,V2,z1,z2,rho,mu,D,L,roughness,use_darcy,mode):
193
  record = bernoulli_pipe_flow(P1,P2,V1,V2,z1,z2,rho,mu,roughness,D,L,None,use_darcy)