Delete stress_gf_xgb.joblib

#6
by OmarOmar91 - opened
This view is limited to 50 files because it contains too many changes.  See the raw diff here.
Files changed (50) hide show
  1. .gitattributes +0 -128
  2. October1.xlsx +0 -0
  3. app.py +164 -724
  4. {papers → literature_pdfs}/Carbon fiber reinforced cement improved by using silane-treated carbon fibers.pdf +0 -0
  5. {papers → literature_pdfs}/Silane-treated carbon fiber for reinforcing cement.pdf +0 -0
  6. papers/1-s2.0-S095006181732278X-main.pdf +0 -3
  7. papers/1-s2.0-S0950061820330786-main.pdf +0 -3
  8. papers/1-s2.0-S1359836816316882-main.pdf +0 -3
  9. papers/1-s2.0-S2090447920301593-main.pdf +0 -3
  10. papers/2011-EffectofSpecimenSizeonStaticStrengthandDIFofHSCfromSHPBTest.pdf +0 -3
  11. papers/Capacitance-based stress self-sensing in cement paste without requiring any admixture.pdf +0 -3
  12. papers/Capacitive compressive stress self-sensing behavior of cement mortar and its dependence on the thickness.pdf +0 -3
  13. papers/Development of self-sensing ultra-high-performance concrete using hybrid carbon black and carbon nanofibers.pdf +0 -3
  14. papers/Development of sensing concrete Principles, properties and its applications.pdf +0 -3
  15. papers/EVALUA~1.PDF +0 -3
  16. papers/Effect of silane treatment on microstructure of sisal fibers.pdf +0 -3
  17. papers/Graphene family (GFMs), carbon nanotubes (CNTs) and carbon black (CB) on smart materials for civil construction.pdf +0 -3
  18. papers/Influence of the structures of polycarboxylate superplasticizer on its performance in cement-based materials-A review.pdf +0 -3
  19. papers/Investigating the synergistic effects of carbon fiber and silica fume on concrete strength and eco-efficiency.pdf +0 -3
  20. papers/Investigation of 3D Printed Self-Sensing UHPC Composites Using Graphite and Hybrid Carbon Microfibers.pdf +0 -3
  21. papers/Ozone treatment of carbon fiber for reinforcing cement.pdf +0 -3
  22. papers/PIEZOE~1.PDF +0 -3
  23. papers/Performance of silica fume slurry treated recycled aggregate concrete reinforced with carbon fibers.pdf +0 -3
  24. papers/Piezopermittivity for capacitance-based strain stress sensing.pdf +0 -3
  25. papers/Review Improving cement-based materials by using silica fume.pdf +0 -3
  26. papers/Revolutionizing infrastructure The evolving landscape of electricity-based multifunctional concrete from concept to practice.pdf +0 -3
  27. papers/S1-An-experimental-study-of-self-sensing-concrete-enhanced_2020_Construction-an.pdf +0 -3
  28. papers/S10-Enhancing-self-stress-sensing-ability-of-smart-ultra-high_2021_Journal-of-Bu.pdf +0 -3
  29. papers/S100-C~1.PDF +0 -3
  30. papers/S11-Environment-Friendly, Self-Sensing Concrete Blended with Byproduct Wastes.pdf +0 -3
  31. papers/S12-Hybrid-effects-of-steel-fiber-and-carbon-nanotube-on-s_2018_Construction-and.pdf +0 -3
  32. papers/S13-Increasing-self-sensing-capability-of-carbon-nanotubes-c_2020_Construction-a.pdf +0 -3
  33. papers/S14-Influence-of-carbon-nanofiber-content-and-sodium-chloride-_2019_Case-Studies.pdf +0 -3
  34. papers/S15-Influence-of-water-ingress-on-the-electrical-properties-_2021_Journal-of-Bui.pdf +0 -3
  35. papers/S16-Investigations-on-scalable-fabrication-procedures-for-sel_2016_Cement-and-Co.pdf +0 -3
  36. papers/S17-Cross tension and compression loading and large-scale testing of strain and damage sensing smart concrete.pdf +0 -3
  37. papers/S18-Nano graphite platelets-enabled piezoresistive cementitious composites for structural health monitoring.pdf +0 -3
  38. papers/S19-Self-sensing-piezoresistive-cement-composite-loaded_2017_Cement-and-Concrete.pdf +0 -3
  39. papers/S2-Characterization-of-smart-brass-fiber-reinforced-co_2020_Construction-and-Bu.pdf +0 -3
  40. papers/S20-IN~1.PDF +0 -3
  41. papers/S21-Mechanical, electrical and self-sensing properties of cementitious mortars containing short carbon fibers.pdf +0 -3
  42. papers/S22-Improved strain sensing properties of cement-based sensors through enhanced carbon nanotube dispersion.pdf +0 -3
  43. papers/S23-Increasing self-sensing capability of carbon nanotubes cement-based materials by simultaneous addition of Ni nanofibers.pdf +0 -3
  44. papers/S24-Multifunctional-self-sensing-and-ductile-cementit_2019_Cement-and-Concrete-R.pdf +0 -3
  45. papers/S25-Self-sensing-capability-of-ultra-high-performance-concr_2018_Sensors-and-Act.pdf +0 -3
  46. papers/S26-TE~1.PDF +0 -3
  47. papers/S27-Effect of aspect ratio on strain sensing capacity of carbon fiber reinforced cement composites.pdf +0 -3
  48. papers/S28-Smart Graphite–Cement Composites with Low Percolation Threshold.pdf +0 -3
  49. papers/S29-Hybrid Carbon Microfibers-Graphite Fillers for Piezoresistive Cementitious Composites.pdf +0 -3
  50. papers/S3-Effect of characteristics of assembly unit of CNTNCB composite fillers on properties of smart cement-based materials.pdf +0 -3
.gitattributes CHANGED
@@ -290,131 +290,3 @@ literature_pdfs/Self-sensing[[:space:]]performance[[:space:]]of[[:space:]]cement
290
  literature_pdfs/Self‐Sensing[[:space:]]Cementitious[[:space:]]Composites[[:space:]]with[[:space:]]Hierarchical[[:space:]]Carbon[[:space:]]Fiber‐Carbon[[:space:]]Nanotube[[:space:]]Composite[[:space:]]Fillers.pdf filter=lfs diff=lfs merge=lfs -text
291
  literature_pdfs/Silane[[:space:]]treatment[[:space:]]of[[:space:]]bagasse[[:space:]]fiber[[:space:]]for[[:space:]]reinforcement[[:space:]]of[[:space:]]cementitious[[:space:]]composites.pdf filter=lfs diff=lfs merge=lfs -text
292
  literature_pdfs/The[[:space:]]effect[[:space:]]of[[:space:]]silane[[:space:]]surface[[:space:]]treatment[[:space:]]on[[:space:]]the[[:space:]]mechanical[[:space:]]properties[[:space:]]of[[:space:]]UHPFRC.pdf filter=lfs diff=lfs merge=lfs -text
293
- papers/1-s2.0-S095006181732278X-main.pdf filter=lfs diff=lfs merge=lfs -text
294
- papers/1-s2.0-S0950061820330786-main.pdf filter=lfs diff=lfs merge=lfs -text
295
- papers/1-s2.0-S1359836816316882-main.pdf filter=lfs diff=lfs merge=lfs -text
296
- papers/1-s2.0-S2090447920301593-main.pdf filter=lfs diff=lfs merge=lfs -text
297
- papers/2011-EffectofSpecimenSizeonStaticStrengthandDIFofHSCfromSHPBTest.pdf filter=lfs diff=lfs merge=lfs -text
298
- papers/document.pdf filter=lfs diff=lfs merge=lfs -text
299
- papers/Capacitance-based[[:space:]]stress[[:space:]]self-sensing[[:space:]]in[[:space:]]cement[[:space:]]paste[[:space:]]without[[:space:]]requiring[[:space:]]any[[:space:]]admixture.pdf filter=lfs diff=lfs merge=lfs -text
300
- papers/Capacitive[[:space:]]compressive[[:space:]]stress[[:space:]]self-sensing[[:space:]]behavior[[:space:]]of[[:space:]]cement[[:space:]]mortar[[:space:]]and[[:space:]]its[[:space:]]dependence[[:space:]]on[[:space:]]the[[:space:]]thickness.pdf filter=lfs diff=lfs merge=lfs -text
301
- papers/Development[[:space:]]of[[:space:]]self-sensing[[:space:]]ultra-high-performance[[:space:]]concrete[[:space:]]using[[:space:]]hybrid[[:space:]]carbon[[:space:]]black[[:space:]]and[[:space:]]carbon[[:space:]]nanofibers.pdf filter=lfs diff=lfs merge=lfs -text
302
- papers/Development[[:space:]]of[[:space:]]sensing[[:space:]]concrete[[:space:]]Principles,[[:space:]]properties[[:space:]]and[[:space:]]its[[:space:]]applications.pdf filter=lfs diff=lfs merge=lfs -text
303
- papers/Effect[[:space:]]of[[:space:]]silane[[:space:]]treatment[[:space:]]on[[:space:]]microstructure[[:space:]]of[[:space:]]sisal[[:space:]]fibers.pdf filter=lfs diff=lfs merge=lfs -text
304
- papers/EVALUA~1.PDF filter=lfs diff=lfs merge=lfs -text
305
- papers/Graphene[[:space:]]family[[:space:]](GFMs),[[:space:]]carbon[[:space:]]nanotubes[[:space:]](CNTs)[[:space:]]and[[:space:]]carbon[[:space:]]black[[:space:]](CB)[[:space:]]on[[:space:]]smart[[:space:]]materials[[:space:]]for[[:space:]]civil[[:space:]]construction.pdf filter=lfs diff=lfs merge=lfs -text
306
- papers/Influence[[:space:]]of[[:space:]]the[[:space:]]structures[[:space:]]of[[:space:]]polycarboxylate[[:space:]]superplasticizer[[:space:]]on[[:space:]]its[[:space:]]performance[[:space:]]in[[:space:]]cement-based[[:space:]]materials-A[[:space:]]review.pdf filter=lfs diff=lfs merge=lfs -text
307
- papers/Investigating[[:space:]]the[[:space:]]synergistic[[:space:]]effects[[:space:]]of[[:space:]]carbon[[:space:]]fiber[[:space:]]and[[:space:]]silica[[:space:]]fume[[:space:]]on[[:space:]]concrete[[:space:]]strength[[:space:]]and[[:space:]]eco-efficiency.pdf filter=lfs diff=lfs merge=lfs -text
308
- papers/Investigation[[:space:]]of[[:space:]]3D[[:space:]]Printed[[:space:]]Self-Sensing[[:space:]]UHPC[[:space:]]Composites[[:space:]]Using[[:space:]]Graphite[[:space:]]and[[:space:]]Hybrid[[:space:]]Carbon[[:space:]]Microfibers.pdf filter=lfs diff=lfs merge=lfs -text
309
- papers/Ozone[[:space:]]treatment[[:space:]]of[[:space:]]carbon[[:space:]]fiber[[:space:]]for[[:space:]]reinforcing[[:space:]]cement.pdf filter=lfs diff=lfs merge=lfs -text
310
- papers/Performance[[:space:]]of[[:space:]]silica[[:space:]]fume[[:space:]]slurry[[:space:]]treated[[:space:]]recycled[[:space:]]aggregate[[:space:]]concrete[[:space:]]reinforced[[:space:]]with[[:space:]]carbon[[:space:]]fibers.pdf filter=lfs diff=lfs merge=lfs -text
311
- papers/PIEZOE~1.PDF filter=lfs diff=lfs merge=lfs -text
312
- papers/Piezopermittivity[[:space:]]for[[:space:]]capacitance-based[[:space:]]strain[[:space:]]stress[[:space:]]sensing.pdf filter=lfs diff=lfs merge=lfs -text
313
- papers/Review[[:space:]]Improving[[:space:]]cement-based[[:space:]]materials[[:space:]]by[[:space:]]using[[:space:]]silica[[:space:]]fume.pdf filter=lfs diff=lfs merge=lfs -text
314
- papers/Revolutionizing[[:space:]]infrastructure[[:space:]]The[[:space:]]evolving[[:space:]]landscape[[:space:]]of[[:space:]]electricity-based[[:space:]]multifunctional[[:space:]]concrete[[:space:]]from[[:space:]]concept[[:space:]]to[[:space:]]practice.pdf filter=lfs diff=lfs merge=lfs -text
315
- papers/S1-An-experimental-study-of-self-sensing-concrete-enhanced_2020_Construction-an.pdf filter=lfs diff=lfs merge=lfs -text
316
- papers/S10-Enhancing-self-stress-sensing-ability-of-smart-ultra-high_2021_Journal-of-Bu.pdf filter=lfs diff=lfs merge=lfs -text
317
- papers/S100-C~1.PDF filter=lfs diff=lfs merge=lfs -text
318
- papers/S11-Environment-Friendly,[[:space:]]Self-Sensing[[:space:]]Concrete[[:space:]]Blended[[:space:]]with[[:space:]]Byproduct[[:space:]]Wastes.pdf filter=lfs diff=lfs merge=lfs -text
319
- papers/S12-Hybrid-effects-of-steel-fiber-and-carbon-nanotube-on-s_2018_Construction-and.pdf filter=lfs diff=lfs merge=lfs -text
320
- papers/S13-Increasing-self-sensing-capability-of-carbon-nanotubes-c_2020_Construction-a.pdf filter=lfs diff=lfs merge=lfs -text
321
- papers/S14-Influence-of-carbon-nanofiber-content-and-sodium-chloride-_2019_Case-Studies.pdf filter=lfs diff=lfs merge=lfs -text
322
- papers/S15-Influence-of-water-ingress-on-the-electrical-properties-_2021_Journal-of-Bui.pdf filter=lfs diff=lfs merge=lfs -text
323
- papers/S16-Investigations-on-scalable-fabrication-procedures-for-sel_2016_Cement-and-Co.pdf filter=lfs diff=lfs merge=lfs -text
324
- papers/S17-Cross[[:space:]]tension[[:space:]]and[[:space:]]compression[[:space:]]loading[[:space:]]and[[:space:]]large-scale[[:space:]]testing[[:space:]]of[[:space:]]strain[[:space:]]and[[:space:]]damage[[:space:]]sensing[[:space:]]smart[[:space:]]concrete.pdf filter=lfs diff=lfs merge=lfs -text
325
- papers/S18-Nano[[:space:]]graphite[[:space:]]platelets-enabled[[:space:]]piezoresistive[[:space:]]cementitious[[:space:]]composites[[:space:]]for[[:space:]]structural[[:space:]]health[[:space:]]monitoring.pdf filter=lfs diff=lfs merge=lfs -text
326
- papers/S19-Self-sensing-piezoresistive-cement-composite-loaded_2017_Cement-and-Concrete.pdf filter=lfs diff=lfs merge=lfs -text
327
- papers/S2-Characterization-of-smart-brass-fiber-reinforced-co_2020_Construction-and-Bu.pdf filter=lfs diff=lfs merge=lfs -text
328
- papers/S20-IN~1.PDF filter=lfs diff=lfs merge=lfs -text
329
- papers/S21-Mechanical,[[:space:]]electrical[[:space:]]and[[:space:]]self-sensing[[:space:]]properties[[:space:]]of[[:space:]]cementitious[[:space:]]mortars[[:space:]]containing[[:space:]]short[[:space:]]carbon[[:space:]]fibers.pdf filter=lfs diff=lfs merge=lfs -text
330
- papers/S22-Improved[[:space:]]strain[[:space:]]sensing[[:space:]]properties[[:space:]]of[[:space:]]cement-based[[:space:]]sensors[[:space:]]through[[:space:]]enhanced[[:space:]]carbon[[:space:]]nanotube[[:space:]]dispersion.pdf filter=lfs diff=lfs merge=lfs -text
331
- papers/S23-Increasing[[:space:]]self-sensing[[:space:]]capability[[:space:]]of[[:space:]]carbon[[:space:]]nanotubes[[:space:]]cement-based[[:space:]]materials[[:space:]]by[[:space:]]simultaneous[[:space:]]addition[[:space:]]of[[:space:]]Ni[[:space:]]nanofibers.pdf filter=lfs diff=lfs merge=lfs -text
332
- papers/S24-Multifunctional-self-sensing-and-ductile-cementit_2019_Cement-and-Concrete-R.pdf filter=lfs diff=lfs merge=lfs -text
333
- papers/S25-Self-sensing-capability-of-ultra-high-performance-concr_2018_Sensors-and-Act.pdf filter=lfs diff=lfs merge=lfs -text
334
- papers/S26-TE~1.PDF filter=lfs diff=lfs merge=lfs -text
335
- papers/S27-Effect[[:space:]]of[[:space:]]aspect[[:space:]]ratio[[:space:]]on[[:space:]]strain[[:space:]]sensing[[:space:]]capacity[[:space:]]of[[:space:]]carbon[[:space:]]fiber[[:space:]]reinforced[[:space:]]cement[[:space:]]composites.pdf filter=lfs diff=lfs merge=lfs -text
336
- papers/S28-Smart[[:space:]]Graphite–Cement[[:space:]]Composites[[:space:]]with[[:space:]]Low[[:space:]]Percolation[[:space:]]Threshold.pdf filter=lfs diff=lfs merge=lfs -text
337
- papers/S29-Hybrid[[:space:]]Carbon[[:space:]]Microfibers-Graphite[[:space:]]Fillers[[:space:]]for[[:space:]]Piezoresistive[[:space:]]Cementitious[[:space:]]Composites.pdf filter=lfs diff=lfs merge=lfs -text
338
- papers/S3-Effect[[:space:]]of[[:space:]]characteristics[[:space:]]of[[:space:]]assembly[[:space:]]unit[[:space:]]of[[:space:]]CNTNCB[[:space:]]composite[[:space:]]fillers[[:space:]]on[[:space:]]properties[[:space:]]of[[:space:]]smart[[:space:]]cement-based[[:space:]]materials.pdf filter=lfs diff=lfs merge=lfs -text
339
- papers/S30-Smart[[:space:]]Graphite–Cement[[:space:]]Composite[[:space:]]for[[:space:]]Roadway-Integrated[[:space:]]Weigh-In-Motion[[:space:]]Sensing.pdf filter=lfs diff=lfs merge=lfs -text
340
- papers/S31-Electrical[[:space:]]and[[:space:]]piezoresistive[[:space:]]properties[[:space:]]of[[:space:]]carbon[[:space:]]nanofiber[[:space:]]cement[[:space:]]mortar[[:space:]]under[[:space:]]different[[:space:]]temperatures[[:space:]]and[[:space:]]water[[:space:]]contents.pdf filter=lfs diff=lfs merge=lfs -text
341
- papers/S32-Self-stress-sensing-smart-concrete-containing-fine-stee_2019_Construction-an.pdf filter=lfs diff=lfs merge=lfs -text
342
- papers/S33-IN~1.PDF filter=lfs diff=lfs merge=lfs -text
343
- papers/S34-Self-sensing-ultra-high-performance-concrete-fo_2021_Sensors-and-Actuators-A.pdf filter=lfs diff=lfs merge=lfs -text
344
- papers/S35-EL~1.PDF filter=lfs diff=lfs merge=lfs -text
345
- papers/S36-Piezoresistivity[[:space:]]enhancement[[:space:]]of[[:space:]]functional[[:space:]]carbon[[:space:]]black[[:space:]]filled[[:space:]]cement-based[[:space:]]sensor[[:space:]]using[[:space:]]polypropylene[[:space:]]fibre.pdf filter=lfs diff=lfs merge=lfs -text
346
- papers/S37-Test[[:space:]]and[[:space:]]Study[[:space:]]on[[:space:]]Electrical[[:space:]]Property[[:space:]]of[[:space:]]Conductive[[:space:]]Concrete.pdf filter=lfs diff=lfs merge=lfs -text
347
- papers/S38[[:space:]]-[[:space:]]Electrical-resistance-based[[:space:]]Sensing[[:space:]]of[[:space:]]Impact[[:space:]][[:space:]]Damage[[:space:]]in[[:space:]]Carbon[[:space:]]Fiber[[:space:]]Reinforced[[:space:]]Cement-based[[:space:]]Materials.pdf filter=lfs diff=lfs merge=lfs -text
348
- papers/S39[[:space:]]-[[:space:]]Electrical[[:space:]]conductivity[[:space:]]of[[:space:]]self-monitoring[[:space:]]CFRC.pdf filter=lfs diff=lfs merge=lfs -text
349
- papers/S4-Effect-of-steel-fiber-and-carbon-black-on-the-self-s_2019_Construction-and-B.pdf filter=lfs diff=lfs merge=lfs -text
350
- papers/S40[[:space:]]-[[:space:]]Resistance[[:space:]]Changes[[:space:]]during[[:space:]]Compression[[:space:]]of[[:space:]]Carbon[[:space:]]Fiber[[:space:]]Cement[[:space:]]COmposites.pdf filter=lfs diff=lfs merge=lfs -text
351
- papers/S41[[:space:]]-[[:space:]]Electrical-resistance-based[[:space:]]damage[[:space:]]self-sensing[[:space:]]in[[:space:]]carbon[[:space:]]fiber[[:space:]]reinforced[[:space:]]cement.pdf filter=lfs diff=lfs merge=lfs -text
352
- papers/S42-SE~1.PDF filter=lfs diff=lfs merge=lfs -text
353
- papers/S43[[:space:]]-[[:space:]]the[[:space:]]100th[[:space:]]anniversary[[:space:]]of[[:space:]]the[[:space:]]four-point[[:space:]]probe[[:space:]]technique[[:space:]]the[[:space:]]role[[:space:]]of[[:space:]]probe[[:space:]]geometries[[:space:]]in[[:space:]]isotropic[[:space:]]andanisotropic[[:space:]]systems.pdf filter=lfs diff=lfs merge=lfs -text
354
- papers/S44-Sensing[[:space:]]performance[[:space:]]of[[:space:]]engineered[[:space:]]cementitious[[:space:]]composites[[:space:]]in[[:space:]]different[[:space:]]application[[:space:]]forms.pdf filter=lfs diff=lfs merge=lfs -text
355
- papers/S45-Insitu[[:space:]]synthesizing[[:space:]]carbon[[:space:]]nanotubes[[:space:]]on[[:space:]]cement[[:space:]]to[[:space:]]develop[[:space:]]self-sensing[[:space:]]cementitious[[:space:]]composites.pdf filter=lfs diff=lfs merge=lfs -text
356
- papers/S46-SE~1.PDF filter=lfs diff=lfs merge=lfs -text
357
- papers/S47-The[[:space:]]applicability[[:space:]]of[[:space:]]shungite[[:space:]]as[[:space:]]an[[:space:]]electrically[[:space:]]conductive[[:space:]]additive[[:space:]]in[[:space:]]cement[[:space:]]composites.pdf filter=lfs diff=lfs merge=lfs -text
358
- papers/S48-Self-sensing[[:space:]]properties[[:space:]]and[[:space:]]piezoresistive[[:space:]]effect[[:space:]]of[[:space:]]high[[:space:]]ductility[[:space:]]cementitious[[:space:]]composite.pdf filter=lfs diff=lfs merge=lfs -text
359
- papers/S49-ME~1.PDF filter=lfs diff=lfs merge=lfs -text
360
- papers/S5-Effects-of-carbon-nanomaterial-type-and-amount-on-self-sensing-_2019_Measure.pdf filter=lfs diff=lfs merge=lfs -text
361
- papers/S50-IM~1.PDF filter=lfs diff=lfs merge=lfs -text
362
- papers/S51-Electrical[[:space:]]and[[:space:]]piezoresistive[[:space:]]properties[[:space:]]of[[:space:]]cement[[:space:]]composites[[:space:]]with[[:space:]]carbon[[:space:]]nanomaterials.pdf filter=lfs diff=lfs merge=lfs -text
363
- papers/S52-Influences[[:space:]]of[[:space:]](MCNT)[[:space:]]fraction,[[:space:]]moisture,[[:space:]]stressstrain[[:space:]]level[[:space:]]on[[:space:]]the[[:space:]]electrical[[:space:]]properties[[:space:]]of[[:space:]]MCNT[[:space:]]of[[:space:]]cement-based[[:space:]]composites.pdf filter=lfs diff=lfs merge=lfs -text
364
- papers/S53-CA~1.PDF filter=lfs diff=lfs merge=lfs -text
365
- papers/S54-Carbon[[:space:]]Nanofibers[[:space:]]Grown[[:space:]]in[[:space:]]CaO[[:space:]]for[[:space:]]Self-Sensing[[:space:]]in[[:space:]]Mortar.pdf filter=lfs diff=lfs merge=lfs -text
366
- papers/S55-Electro-mechanical[[:space:]]self-sensing[[:space:]]response[[:space:]]of[[:space:]]ultra-high-performance[[:space:]]fiber-reinforced[[:space:]]concrete[[:space:]]in[[:space:]]tension.pdf filter=lfs diff=lfs merge=lfs -text
367
- papers/S55-Nanocarbon[[:space:]]black-based[[:space:]]ultra-high-performance[[:space:]]concrete[[:space:]](UHPC)[[:space:]]with[[:space:]]self-strain[[:space:]]sensing[[:space:]]capability.pdf filter=lfs diff=lfs merge=lfs -text
368
- papers/S56-Self-sensing[[:space:]]cementitious[[:space:]]composites[[:space:]]incorporated[[:space:]]with[[:space:]]botryoid[[:space:]]hybrid[[:space:]]nano-carbon[[:space:]]materials[[:space:]]for[[:space:]]smart[[:space:]]infrastructures.pdf filter=lfs diff=lfs merge=lfs -text
369
- papers/S57-IN~1.PDF filter=lfs diff=lfs merge=lfs -text
370
- papers/S58-DE~1.PDF filter=lfs diff=lfs merge=lfs -text
371
- papers/S59-Modifying[[:space:]]self-sensing[[:space:]]cement-based[[:space:]]composites[[:space:]]through[[:space:]]multiscale[[:space:]]composition.pdf filter=lfs diff=lfs merge=lfs -text
372
- papers/S6-Electrically[[:space:]]conductive[[:space:]]behaviors[[:space:]]and[[:space:]]mechanisms[[:space:]]of[[:space:]]short-cut[[:space:]]super-fine[[:space:]]stainless[[:space:]]wire[[:space:]]reinforced[[:space:]]reactive[[:space:]]powder[[:space:]]concrete.pdf filter=lfs diff=lfs merge=lfs -text
373
- papers/S60-Study[[:space:]]on[[:space:]]self-sensing[[:space:]]capabilities[[:space:]]of[[:space:]]smart[[:space:]]cements[[:space:]]filled[[:space:]]with[[:space:]]graphene[[:space:]]oxide[[:space:]]under[[:space:]]dynamic[[:space:]]cyclic[[:space:]]loading.pdf filter=lfs diff=lfs merge=lfs -text
374
- papers/S61-Piezoresistivity,[[:space:]]mechanisms[[:space:]]and[[:space:]]model[[:space:]]of[[:space:]]cement-based[[:space:]]materials[[:space:]]with[[:space:]]CNT_NCB[[:space:]]composite[[:space:]]fillers.pdf filter=lfs diff=lfs merge=lfs -text
375
- papers/S62-MU~1.PDF filter=lfs diff=lfs merge=lfs -text
376
- papers/S63-Piezoresistive[[:space:]]properties[[:space:]]of[[:space:]]cement[[:space:]]composites[[:space:]]with[[:space:]]expanded[[:space:]]graphite.pdf filter=lfs diff=lfs merge=lfs -text
377
- papers/S64-Electrical[[:space:]]Properties[[:space:]]of[[:space:]]Cement-Based[[:space:]]Composites[[:space:]]with[[:space:]]Carbon[[:space:]]Nanotubes,[[:space:]]Graphene,[[:space:]]and[[:space:]]Graphite[[:space:]]Nanofibers.pdf filter=lfs diff=lfs merge=lfs -text
378
- papers/S65-AN~1.PDF filter=lfs diff=lfs merge=lfs -text
379
- papers/S66-Experimental[[:space:]]Investigation[[:space:]]of[[:space:]]the[[:space:]]Piezoresistive[[:space:]]Properties[[:space:]]of[[:space:]]Cement[[:space:]]Composites[[:space:]]with[[:space:]]Hybrid[[:space:]]Carbon[[:space:]]Fibers[[:space:]]and[[:space:]]Nanotubes.pdf filter=lfs diff=lfs merge=lfs -text
380
- papers/S67-Strain[[:space:]]and[[:space:]]damage[[:space:]]sensing[[:space:]]properties[[:space:]]on[[:space:]]multifunctional[[:space:]]cement[[:space:]]composites[[:space:]]with[[:space:]]CNF[[:space:]]admixture.pdf filter=lfs diff=lfs merge=lfs -text
381
- papers/S68-EF~1.PDF filter=lfs diff=lfs merge=lfs -text
382
- papers/S69-Cement-based[[:space:]]sensors[[:space:]]with[[:space:]]carbon[[:space:]]fibers[[:space:]]and[[:space:]]carbon[[:space:]]nanotubes[[:space:]]for[[:space:]]piezoresistive[[:space:]]sensing.pdf filter=lfs diff=lfs merge=lfs -text
383
- papers/S7-Electrical[[:space:]]characteristics[[:space:]]and[[:space:]]pressure-sensitive[[:space:]]response[[:space:]]measurements[[:space:]]of[[:space:]]carboxyl[[:space:]]MWNT_cement[[:space:]]composites.pdf filter=lfs diff=lfs merge=lfs -text
384
- papers/S70-EV~1.PDF filter=lfs diff=lfs merge=lfs -text
385
- papers/S71-Enhanced[[:space:]]sensing[[:space:]]performance[[:space:]]of[[:space:]]cement-based[[:space:]]composites[[:space:]]achieved[[:space:]]via[[:space:]]magnetically[[:space:]]aligned[[:space:]]nickel[[:space:]]particle[[:space:]]network.pdf filter=lfs diff=lfs merge=lfs -text
386
- papers/S72-Anisotropic[[:space:]]electrical[[:space:]]and[[:space:]]piezoresistive[[:space:]]sensing[[:space:]]properties[[:space:]]of[[:space:]]cement-based[[:space:]]sensors[[:space:]]with[[:space:]]aligned[[:space:]]carbon[[:space:]]fibers.pdf filter=lfs diff=lfs merge=lfs -text
387
- papers/S73-Development[[:space:]]of[[:space:]]self-sensing[[:space:]]cement-based[[:space:]]sensor[[:space:]]using[[:space:]]recycled[[:space:]]fine[[:space:]]waste[[:space:]]glass[[:space:]]aggregates[[:space:]]coated[[:space:]]with[[:space:]]carbon[[:space:]]nanotube.pdf filter=lfs diff=lfs merge=lfs -text
388
- papers/S74-Strain[[:space:]]sensitivity[[:space:]]of[[:space:]]steel-fiber-reinforced[[:space:]]industrial[[:space:]]smart[[:space:]]concrete.pdf filter=lfs diff=lfs merge=lfs -text
389
- papers/S75-SE~1.PDF filter=lfs diff=lfs merge=lfs -text
390
- papers/S76-Strain-sensing[[:space:]]characteristics[[:space:]]of[[:space:]]self-consolidating[[:space:]]concrete[[:space:]]with[[:space:]]micro-carbon[[:space:]]fibre.pdf filter=lfs diff=lfs merge=lfs -text
391
- papers/S77-SE~1.PDF filter=lfs diff=lfs merge=lfs -text
392
- papers/S78-Mechanical[[:space:]]and[[:space:]]self-sensing[[:space:]]properties[[:space:]]of[[:space:]]concrete[[:space:]]reinforced[[:space:]]with[[:space:]]carbon[[:space:]]nanofibres.pdf filter=lfs diff=lfs merge=lfs -text
393
- papers/S79-Carbon[[:space:]]nanotube[[:space:]]cement-based[[:space:]]transducers[[:space:]]for[[:space:]]dynamic[[:space:]]sensing[[:space:]]of[[:space:]]strain.pdf filter=lfs diff=lfs merge=lfs -text
394
- papers/S8-Electrically-cured-ultra-high-performance-concrete--UHPC--embe_2020_Material.pdf filter=lfs diff=lfs merge=lfs -text
395
- papers/S80-MA~1.PDF filter=lfs diff=lfs merge=lfs -text
396
- papers/S81-Piezoresistive[[:space:]]properties[[:space:]]of[[:space:]]ultra-high-performance[[:space:]]fiber-reinforced[[:space:]]concrete[[:space:]]incorporating[[:space:]]few-layer[[:space:]]graphene.pdf filter=lfs diff=lfs merge=lfs -text
397
- papers/S82-SY~1.PDF filter=lfs diff=lfs merge=lfs -text
398
- papers/S83-Effect[[:space:]]of[[:space:]]compressive[[:space:]]strain[[:space:]]on[[:space:]]electrical[[:space:]]resistivity[[:space:]]of[[:space:]]carbon[[:space:]]black-filled[[:space:]]cement-based[[:space:]]composites.pdf filter=lfs diff=lfs merge=lfs -text
399
- papers/S84-TA~1.PDF filter=lfs diff=lfs merge=lfs -text
400
- papers/S85-Performance[[:space:]]of[[:space:]]cement-based[[:space:]]sensors[[:space:]]with[[:space:]]CNT[[:space:]]for[[:space:]]strain[[:space:]]sensing.pdf filter=lfs diff=lfs merge=lfs -text
401
- papers/S86-EL~1.PDF filter=lfs diff=lfs merge=lfs -text
402
- papers/S87-EL~1.PDF filter=lfs diff=lfs merge=lfs -text
403
- papers/S88-ST~1.PDF filter=lfs diff=lfs merge=lfs -text
404
- papers/S89-Piezoresistivity[[:space:]]of[[:space:]]carbon[[:space:]]fiber[[:space:]]graphite[[:space:]]cement-based[[:space:]]composites[[:space:]]with[[:space:]]CCCW.pdf filter=lfs diff=lfs merge=lfs -text
405
- papers/S9-Electro-mechanical-self-sensing-response-of-ultra-high-_2018_Composites-Part.pdf filter=lfs diff=lfs merge=lfs -text
406
- papers/S90-EX~1.PDF filter=lfs diff=lfs merge=lfs -text
407
- papers/S91-A[[:space:]]comparative[[:space:]]study[[:space:]]on[[:space:]]the[[:space:]]influences[[:space:]]of[[:space:]]CNT[[:space:]]and[[:space:]]GNP[[:space:]]on[[:space:]]the[[:space:]]piezoresistivity[[:space:]]of[[:space:]]cement[[:space:]]composites.pdf filter=lfs diff=lfs merge=lfs -text
408
- papers/S92-Research-on-the-self-sensing-and-mechanical-properties-of_2021_Cement-and-Co.pdf filter=lfs diff=lfs merge=lfs -text
409
- papers/S93-Enhanced[[:space:]]effects[[:space:]]of[[:space:]]carbon-based[[:space:]]conductive[[:space:]]materials[[:space:]]on[[:space:]]the[[:space:]]piezoresistive[[:space:]]characteristics[[:space:]]of[[:space:]]cementitious[[:space:]]composites.pdf filter=lfs diff=lfs merge=lfs -text
410
- papers/S94-The[[:space:]]Utilization[[:space:]]of[[:space:]]Pearson’s[[:space:]]Method[[:space:]]to[[:space:]]Analyze[[:space:]]Piezoresistive[[:space:]]Effect[[:space:]]in[[:space:]]Self-Sensing[[:space:]]Cement[[:space:]]Composite[[:space:]]with[[:space:]]Graphite.pdf filter=lfs diff=lfs merge=lfs -text
411
- papers/S95-SE~1.PDF filter=lfs diff=lfs merge=lfs -text
412
- papers/S96-EL~1.PDF filter=lfs diff=lfs merge=lfs -text
413
- papers/S97-Self-sensing[[:space:]]GFRP-reinforced[[:space:]]concrete[[:space:]]beams[[:space:]]containing[[:space:]]carbon[[:space:]]nanotube-nano[[:space:]]carbon[[:space:]]black[[:space:]]composite[[:space:]]fillers.pdf filter=lfs diff=lfs merge=lfs -text
414
- papers/S98-MI~1.PDF filter=lfs diff=lfs merge=lfs -text
415
- papers/S99-Commercial[[:space:]]and[[:space:]]recycled[[:space:]]carbon-based[[:space:]]fillers[[:space:]]and[[:space:]]fibers[[:space:]]for[[:space:]]self-sensing[[:space:]]cement-based[[:space:]]composites.pdf filter=lfs diff=lfs merge=lfs -text
416
- papers/Self-sensing[[:space:]]enhancement[[:space:]]in[[:space:]]smart[[:space:]]ultra-high[[:space:]]performance[[:space:]]concrete[[:space:]]composites[[:space:]]via[[:space:]]multi-scale[[:space:]]carbon[[:space:]]black.pdf filter=lfs diff=lfs merge=lfs -text
417
- papers/Self-sensing[[:space:]]performance[[:space:]]of[[:space:]]cementitious[[:space:]]composites[[:space:]]with[[:space:]]functional[[:space:]]fillers[[:space:]]at[[:space:]]macro,[[:space:]]micro[[:space:]]and[[:space:]]nano[[:space:]]scales.pdf filter=lfs diff=lfs merge=lfs -text
418
- papers/Self‐Sensing[[:space:]]Cementitious[[:space:]]Composites[[:space:]]with[[:space:]]Hierarchical[[:space:]]Carbon[[:space:]]Fiber‐Carbon[[:space:]]Nanotube[[:space:]]Composite[[:space:]]Fillers.pdf filter=lfs diff=lfs merge=lfs -text
419
- papers/Silane[[:space:]]treatment[[:space:]]of[[:space:]]bagasse[[:space:]]fiber[[:space:]]for[[:space:]]reinforcement[[:space:]]of[[:space:]]cementitious[[:space:]]composites.pdf filter=lfs diff=lfs merge=lfs -text
420
- papers/The[[:space:]]effect[[:space:]]of[[:space:]]silane[[:space:]]surface[[:space:]]treatment[[:space:]]on[[:space:]]the[[:space:]]mechanical[[:space:]]properties[[:space:]]of[[:space:]]UHPFRC.pdf filter=lfs diff=lfs merge=lfs -text
 
290
  literature_pdfs/Self‐Sensing[[:space:]]Cementitious[[:space:]]Composites[[:space:]]with[[:space:]]Hierarchical[[:space:]]Carbon[[:space:]]Fiber‐Carbon[[:space:]]Nanotube[[:space:]]Composite[[:space:]]Fillers.pdf filter=lfs diff=lfs merge=lfs -text
291
  literature_pdfs/Silane[[:space:]]treatment[[:space:]]of[[:space:]]bagasse[[:space:]]fiber[[:space:]]for[[:space:]]reinforcement[[:space:]]of[[:space:]]cementitious[[:space:]]composites.pdf filter=lfs diff=lfs merge=lfs -text
292
  literature_pdfs/The[[:space:]]effect[[:space:]]of[[:space:]]silane[[:space:]]surface[[:space:]]treatment[[:space:]]on[[:space:]]the[[:space:]]mechanical[[:space:]]properties[[:space:]]of[[:space:]]UHPFRC.pdf filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
October1.xlsx DELETED
Binary file (95.1 kB)
 
app.py CHANGED
@@ -1,12 +1,8 @@
1
- # ================================================================
2
  # Self-Sensing Concrete Assistant — Predictor (XGB) + Hybrid RAG
3
- # - Uses local 'papers/' folder for literature
4
- # - Robust MMR sentence selection (no list index errors)
5
- # - Predictor: safe model caching + safe feature alignment
6
- # - Stable categoricals ("NA"); no over-strict completeness gate
7
- # - Lightweight instrumentation (JSONL logs per RAG turn)
8
- # - Dark-blue theme + Evaluate tab + k-slider styling
9
- # - Citations use SHORT CODES (e.g., S71, S92) from filenames
10
  # ================================================================
11
 
12
  # ---------------------- Runtime flags (HF-safe) ----------------------
@@ -16,9 +12,9 @@ os.environ["TRANSFORMERS_NO_FLAX"] = "1"
16
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
17
 
18
  # ------------------------------- Imports ------------------------------
19
- import re, joblib, warnings, json, traceback, time, uuid, subprocess, sys
20
  from pathlib import Path
21
- from typing import List, Dict, Any, Optional
22
 
23
  import numpy as np
24
  import pandas as pd
@@ -39,21 +35,20 @@ except Exception:
39
  BM25Okapi = None
40
  print("rank_bm25 not installed; BM25 disabled (TF-IDF still works).")
41
 
42
- # Optional OpenAI (for LLM synthesis)
43
  OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
44
- OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-5")
 
45
  try:
46
  from openai import OpenAI
47
  except Exception:
48
  OpenAI = None
49
 
50
- # LLM availability flag — used internally; UI remains hidden
51
- LLM_AVAILABLE = (OPENAI_API_KEY is not None and OPENAI_API_KEY.strip() != "" and OpenAI is not None)
52
 
53
- # ========================= Predictor (kept) =========================
54
  CF_COL = "Conductive Filler Conc. (wt%)"
55
  TARGET_COL = "Stress GF (MPa-1)"
56
- CANON_NA = "NA" # canonical placeholder for categoricals
57
 
58
  MAIN_VARIABLES = [
59
  "Filler 1 Type",
@@ -110,133 +105,54 @@ CATEGORICAL_COLS = {
110
  "Current Type"
111
  }
112
 
113
- DIM_CHOICES = ["0D", "1D", "2D", "3D", CANON_NA]
114
- CURRENT_CHOICES = ["DC", "AC", CANON_NA]
115
 
116
  MODEL_CANDIDATES = [
117
  "stress_gf_xgb.joblib",
118
  "models/stress_gf_xgb.joblib",
119
  "/home/user/app/stress_gf_xgb.joblib",
120
- os.getenv("MODEL_PATH", "")
121
  ]
122
 
123
- # ---------- Model caching + status ----------
124
- MODEL = None
125
- MODEL_STATUS = "🔴 Model not loaded"
126
-
127
- def _try_load_model():
128
- global MODEL, MODEL_STATUS
129
- for p in [x for x in MODEL_CANDIDATES if x]:
130
  if os.path.exists(p):
131
  try:
132
- MODEL = joblib.load(p)
133
- MODEL_STATUS = f"🟢 Loaded model: {Path(p).name}"
134
- print("[ModelLoad] Loaded:", p)
135
- return
136
  except Exception as e:
137
- print(f"[ModelLoad] Error from {p}: {e}")
138
- traceback.print_exc()
139
- MODEL = None
140
- if MODEL is None:
141
- MODEL_STATUS = "🔴 Model not found (place stress_gf_xgb.joblib at repo root or models/, or set MODEL_PATH)"
142
- print("[ModelLoad]", MODEL_STATUS)
143
-
144
- _try_load_model() # load at import time
145
-
146
- def _canon_cat(v: Any) -> str:
147
- """Stable, canonical category placeholder normalization."""
148
- if v is None:
149
- return CANON_NA
150
- s = str(v).strip()
151
- if s == "" or s.upper() in {"N/A", "NONE", "NULL"}:
152
- return CANON_NA
153
- return s
154
-
155
- def _to_float_or_nan(v):
156
- if v in ("", None):
157
- return np.nan
158
- try:
159
- return float(str(v).replace(",", ""))
160
- except Exception:
161
- return np.nan
162
 
163
  def _coerce_to_row(form_dict: dict) -> pd.DataFrame:
164
  row = {}
165
  for col in MAIN_VARIABLES:
166
  v = form_dict.get(col, None)
167
  if col in NUMERIC_COLS:
168
- row[col] = _to_float_or_nan(v)
169
- elif col in CATEGORICAL_COLS:
170
- row[col] = _canon_cat(v)
 
 
 
 
171
  else:
172
- s = str(v).strip() if v is not None else ""
173
- row[col] = s if s else CANON_NA
174
  return pd.DataFrame([row], columns=MAIN_VARIABLES)
175
 
176
- def _align_columns_to_model(df: pd.DataFrame, mdl) -> pd.DataFrame:
177
- """
178
- SAFE alignment:
179
- - If mdl.feature_names_in_ exists AND is a subset of df.columns (raw names), reorder to it.
180
- - Else, try a Pipeline step (e.g., 'preprocessor') with feature_names_in_ subset of df.columns.
181
- - Else, DO NOT align (let the pipeline handle columns by name).
182
- """
183
- try:
184
- feat = getattr(mdl, "feature_names_in_", None)
185
- if isinstance(feat, (list, np.ndarray, pd.Index)):
186
- feat = list(feat)
187
- if all(c in df.columns for c in feat):
188
- return df[feat]
189
-
190
- if hasattr(mdl, "named_steps"):
191
- for key in ["preprocessor", "columntransformer"]:
192
- if key in mdl.named_steps:
193
- step = mdl.named_steps[key]
194
- feat2 = getattr(step, "feature_names_in_", None)
195
- if isinstance(feat2, (list, np.ndarray, pd.Index)):
196
- feat2 = list(feat2)
197
- if all(c in df.columns for c in feat2):
198
- return df[feat2]
199
- # fallback to first step if it exposes input names
200
- try:
201
- first_key = list(mdl.named_steps.keys())[0]
202
- step = mdl.named_steps[first_key]
203
- feat3 = getattr(step, "feature_names_in_", None)
204
- if isinstance(feat3, (list, np.ndarray, pd.Index)):
205
- feat3 = list(feat3)
206
- if all(c in df.columns for c in feat3):
207
- return df[feat3]
208
- except Exception:
209
- pass
210
-
211
- return df
212
- except Exception as e:
213
- print(f"[Align] Skip aligning due to: {e}")
214
- traceback.print_exc()
215
- return df
216
-
217
  def predict_fn(**kwargs):
218
- """
219
- Always attempt prediction.
220
- - Missing numerics -> NaN (imputer handles)
221
- - Categoricals -> 'NA'
222
- - If model missing or inference error -> 0.0 (keeps UI stable)
223
- """
224
- if MODEL is None:
225
- return 0.0
226
  X_new = _coerce_to_row(kwargs)
227
- X_new = _align_columns_to_model(X_new, MODEL)
228
  try:
229
- y_raw = MODEL.predict(X_new) # log1p or original scale depending on training
230
- if getattr(MODEL, "target_is_log1p_", False):
231
- y = np.expm1(y_raw)
232
- else:
233
- y = y_raw
234
- y = float(np.asarray(y).ravel()[0])
235
- return max(y, 0.0)
236
  except Exception as e:
237
- print(f"[Predict] {e}")
238
- traceback.print_exc()
239
- return 0.0
240
 
241
  EXAMPLE = {
242
  "Filler 1 Type": "CNT",
@@ -245,7 +161,7 @@ EXAMPLE = {
245
  "Filler 1 Length (mm)": 1.2,
246
  CF_COL: 0.5,
247
  "Filler 2 Type": "",
248
- "Filler 2 Dimensionality": CANON_NA,
249
  "Filler 2 Diameter (µm)": None,
250
  "Filler 2 Length (mm)": None,
251
  "Specimen Volume (mm3)": 1000,
@@ -273,14 +189,15 @@ def _clear_all():
273
  if col in NUMERIC_COLS:
274
  cleared.append(None)
275
  elif col in {"Filler 1 Dimensionality", "Filler 2 Dimensionality"}:
276
- cleared.append(CANON_NA)
277
  elif col == "Current Type":
278
- cleared.append(CANON_NA)
279
  else:
280
  cleared.append("")
281
  return cleared
282
 
283
- # ========================= Hybrid RAG =========================
 
284
  ARTIFACT_DIR = Path("rag_artifacts"); ARTIFACT_DIR.mkdir(exist_ok=True)
285
  TFIDF_VECT_PATH = ARTIFACT_DIR / "tfidf_vectorizer.joblib"
286
  TFIDF_MAT_PATH = ARTIFACT_DIR / "tfidf_matrix.joblib"
@@ -288,13 +205,16 @@ BM25_TOK_PATH = ARTIFACT_DIR / "bm25_tokens.joblib"
288
  EMB_NPY_PATH = ARTIFACT_DIR / "chunk_embeddings.npy"
289
  RAG_META_PATH = ARTIFACT_DIR / "chunks.parquet"
290
 
291
- LOCAL_PDF_DIR = Path("papers"); LOCAL_PDF_DIR.mkdir(exist_ok=True)
 
292
  USE_ONLINE_SOURCES = os.getenv("USE_ONLINE_SOURCES", "false").lower() == "true"
293
 
 
294
  W_TFIDF_DEFAULT = 0.50 if not USE_DENSE else 0.30
295
  W_BM25_DEFAULT = 0.50 if not USE_DENSE else 0.30
296
- W_EMB_DEFAULT = 0.00 if USE_DENSE is False else 0.40
297
 
 
298
  _SENT_SPLIT_RE = re.compile(r"(?<=[.!?])\s+|\n+")
299
  TOKEN_RE = re.compile(r"[A-Za-z0-9_#+\-/\.%]+")
300
  def sent_split(text: str) -> List[str]:
@@ -303,6 +223,7 @@ def sent_split(text: str) -> List[str]:
303
  def tokenize(text: str) -> List[str]:
304
  return [t.lower() for t in TOKEN_RE.findall(text)]
305
 
 
306
  def _extract_pdf_text(pdf_path: Path) -> str:
307
  try:
308
  import fitz
@@ -344,8 +265,8 @@ def _safe_init_st_model(name: str):
344
  USE_DENSE = False
345
  return None
346
 
 
347
  def build_or_load_hybrid(pdf_dir: Path):
348
- # Build or load the hybrid retriever cache
349
  have_cache = (TFIDF_VECT_PATH.exists() and TFIDF_MAT_PATH.exists()
350
  and RAG_META_PATH.exists()
351
  and (BM25_TOK_PATH.exists() or BM25Okapi is None)
@@ -369,11 +290,13 @@ def build_or_load_hybrid(pdf_dir: Path):
369
  rows.append({"doc_path": str(pdf), "chunk_id": i, "text": ch})
370
  all_tokens.append(tokenize(ch))
371
  if not rows:
 
372
  meta = pd.DataFrame(columns=["doc_path", "chunk_id", "text"])
373
  vectorizer = None; X_tfidf = None; emb = None; all_tokens = None
374
  return vectorizer, X_tfidf, meta, all_tokens, emb
375
 
376
  meta = pd.DataFrame(rows)
 
377
  from sklearn.feature_extraction.text import TfidfVectorizer
378
  vectorizer = TfidfVectorizer(
379
  ngram_range=(1,2),
@@ -397,11 +320,13 @@ def build_or_load_hybrid(pdf_dir: Path):
397
  print("Dense embedding failed:", e)
398
  emb = None
399
 
 
400
  joblib.dump(vectorizer, TFIDF_VECT_PATH)
401
  joblib.dump(X_tfidf, TFIDF_MAT_PATH)
402
  if BM25Okapi is not None:
403
  joblib.dump(all_tokens, BM25_TOK_PATH)
404
  meta.to_parquet(RAG_META_PATH, index=False)
 
405
  return vectorizer, X_tfidf, meta, all_tokens, emb
406
 
407
  tfidf_vectorizer, tfidf_matrix, rag_meta, bm25_tokens, emb_matrix = build_or_load_hybrid(LOCAL_PDF_DIR)
@@ -409,29 +334,9 @@ bm25 = BM25Okapi(bm25_tokens) if (BM25Okapi is not None and bm25_tokens is not N
409
  st_query_model = _safe_init_st_model(os.getenv("EMB_MODEL_NAME", "sentence-transformers/all-MiniLM-L6-v2"))
410
 
411
  def _extract_page(text_chunk: str) -> str:
412
- # Correct: [[PAGE=123]]
413
  m = list(re.finditer(r"\[\[PAGE=(\d+)\]\]", text_chunk or ""))
414
  return (m[-1].group(1) if m else "?")
415
 
416
- def _short_doc_code(doc_path: str) -> str:
417
- """
418
- Turn a full filename like:
419
- 'S92-Research-on-the-self-sensing-and-mechanical-properties-of_2021_Cement-and-Co.pdf'
420
- into a short code:
421
- 'S92'
422
- For generic names, falls back to the first token of the stem.
423
- """
424
- if not doc_path:
425
- return "Source"
426
- name = Path(doc_path).name
427
- stem = name.rsplit(".", 1)[0]
428
- # Split on whitespace, hyphen, underscore
429
- parts = re.split(r"[ \t\n\r\-_]+", stem)
430
- for p in parts:
431
- if p:
432
- return p
433
- return stem or "Source"
434
-
435
  def hybrid_search(query: str, k=8, w_tfidf=W_TFIDF_DEFAULT, w_bm25=W_BM25_DEFAULT, w_emb=W_EMB_DEFAULT):
436
  if rag_meta is None or rag_meta.empty:
437
  return pd.DataFrame()
@@ -458,7 +363,7 @@ def hybrid_search(query: str, k=8, w_tfidf=W_TFIDF_DEFAULT, w_bm25=W_BM25_DEFAUL
458
 
459
  # BM25 scores
460
  if bm25 is not None:
461
- q_tokens = [t.lower() for t in re.findall(r"[A-Za-z0-9_#+\-\/\.%]+", query)]
462
  bm25_scores = np.array(bm25.get_scores(q_tokens), dtype=float)
463
  else:
464
  bm25_scores = np.zeros(len(rag_meta), dtype=float); w_bm25 = 0.0
@@ -490,114 +395,71 @@ def split_sentences(text: str) -> List[str]:
490
  return [s for s in sents if 6 <= len(s.split()) <= 60]
491
 
492
  def mmr_select_sentences(question: str, hits: pd.DataFrame, top_n=4, pool_per_chunk=6, lambda_div=0.7):
493
- """
494
- Robust MMR sentence picker:
495
- - Handles empty pools
496
- - Clamps top_n to pool size
497
- - Avoids 'list index out of range'
498
- """
499
- # Build pool
500
  pool = []
501
  for _, row in hits.iterrows():
502
- doc_code = _short_doc_code(row["doc_path"])
503
  page = _extract_page(row["text"])
504
- sents = split_sentences(row["text"])
505
- if not sents:
506
- continue
507
- for s in sents[:max(1, int(pool_per_chunk))]:
508
- pool.append({"sent": s, "doc": doc_code, "page": page})
509
-
510
  if not pool:
511
  return []
512
 
513
- # Relevance vectors
514
  sent_texts = [p["sent"] for p in pool]
 
 
515
  use_dense = USE_DENSE and st_query_model is not None
516
- try:
517
- if use_dense:
518
  from sklearn.preprocessing import normalize as sk_normalize
519
- enc = st_query_model.encode([question] + sent_texts, convert_to_numpy=True)
 
520
  q_vec = sk_normalize(enc[:1])[0]
521
  S = sk_normalize(enc[1:])
522
  rel = (S @ q_vec)
523
  def sim_fn(i, j): return float(S[i] @ S[j])
524
- else:
525
- from sklearn.feature_extraction.text import TfidfVectorizer
526
- vect = TfidfVectorizer().fit(sent_texts + [question])
527
- Q = vect.transform([question]); S = vect.transform(sent_texts)
528
- rel = (S @ Q.T).toarray().ravel()
529
- def sim_fn(i, j):
530
- num = (S[i] @ S[j].T)
531
- return float(num.toarray()[0, 0]) if hasattr(num, "toarray") else float(num)
532
- except Exception:
533
- # Fallback: uniform relevance if vectorization fails
534
- rel = np.ones(len(sent_texts), dtype=float)
535
- def sim_fn(i, j): return 0.0
536
 
537
- # Normalize lambda_div
538
- lambda_div = float(np.clip(lambda_div, 0.0, 1.0))
 
 
 
 
539
 
540
- # Select first by highest relevance
541
  remain = list(range(len(pool)))
542
- if not remain:
543
- return []
544
  first = int(np.argmax(rel))
545
- selected_idx = [first]
546
- selected = [pool[first]]
547
- remain.remove(first)
548
 
549
- # Clamp top_n
550
- max_pick = min(int(top_n), len(pool))
551
- while len(selected) < max_pick and remain:
552
  cand_scores = []
553
  for i in remain:
554
- div_i = max(sim_fn(i, j) for j in selected_idx) if selected_idx else 0.0
555
- score = lambda_div * float(rel[i]) - (1.0 - lambda_div) * div_i
556
  cand_scores.append((score, i))
557
- if not cand_scores:
558
- break
559
  cand_scores.sort(reverse=True)
560
- _, best_i = cand_scores[0]
561
- selected_idx.append(best_i)
562
- selected.append(pool[best_i])
563
- remain.remove(best_i)
564
-
565
  return selected
566
 
567
  def compose_extractive(selected: List[Dict[str, Any]]) -> str:
568
  if not selected:
569
  return ""
570
- # Citations inside answer are short codes only, e.g. (S92), (S71)
571
- return " ".join(f"{s['sent']} ({s['doc']})" for s in selected)
572
-
573
- # ========================= NEW: Instrumentation helpers =========================
574
- LOG_PATH = ARTIFACT_DIR / "rag_logs.jsonl"
575
- OPENAI_IN_COST_PER_1K = float(os.getenv("OPENAI_COST_IN_PER_1K", "0"))
576
- OPENAI_OUT_COST_PER_1K = float(os.getenv("OPENAI_COST_OUT_PER_1K", "0"))
577
 
578
- def _safe_write_jsonl(path: Path, record: dict):
579
- try:
580
- with open(path, "a", encoding="utf-8") as f:
581
- f.write(json.dumps(record, ensure_ascii=False) + "\n")
582
- except Exception as e:
583
- print("[Log] write failed:", e)
584
-
585
- def _calc_cost_usd(prompt_toks, completion_toks):
586
- if prompt_toks is None or completion_toks is None:
587
  return None
588
- return (prompt_toks / 1000.0) * OPENAI_IN_COST_PER_1K + (completion_toks / 1000.0) * OPENAI_OUT_COST_PER_1K
589
-
590
- # ----------------- Modified to return (text, usage_dict) -----------------
591
- def synthesize_with_llm(question: str, sentence_lines: List[str], model: str = None, temperature: float = 0.2):
592
- if not LLM_AVAILABLE:
593
- return None, None
594
  client = OpenAI(api_key=OPENAI_API_KEY)
595
  model = model or OPENAI_MODEL
 
596
  SYSTEM_PROMPT = (
597
  "You are a scientific assistant for self-sensing cementitious materials.\n"
598
  "Answer STRICTLY using the provided sentences.\n"
599
  "Do not invent facts. Keep it concise (3–6 sentences).\n"
600
- "Retain inline citations exactly as given (e.g., (S92), (S92; S71))."
601
  )
602
  user_prompt = (
603
  f"Question: {question}\n\n"
@@ -613,186 +475,61 @@ def synthesize_with_llm(question: str, sentence_lines: List[str], model: str = N
613
  ],
614
  temperature=temperature,
615
  )
616
- out_text = getattr(resp, "output_text", None) or str(resp)
617
- usage = None
618
- try:
619
- u = getattr(resp, "usage", None)
620
- if u:
621
- pt = getattr(u, "prompt_tokens", None) if hasattr(u, "prompt_tokens") else u.get("prompt_tokens", None)
622
- ct = getattr(u, "completion_tokens", None) if hasattr(u, "completion_tokens") else u.get("completion_tokens", None)
623
- usage = {"prompt_tokens": pt, "completion_tokens": ct}
624
- except Exception:
625
- usage = None
626
- return out_text, usage
627
- except Exception:
628
- return None, None
629
 
630
  def rag_reply(
631
  question: str,
632
  k: int = 8,
633
  n_sentences: int = 4,
634
  include_passages: bool = False,
635
- use_llm: bool = False,
636
- model: str = None,
637
  temperature: float = 0.2,
638
  strict_quotes_only: bool = False,
639
  w_tfidf: float = W_TFIDF_DEFAULT,
640
  w_bm25: float = W_BM25_DEFAULT,
641
  w_emb: float = W_EMB_DEFAULT
642
  ) -> str:
643
- run_id = str(uuid.uuid4())
644
- t0_total = time.time()
645
- t0_retr = time.time()
646
-
647
- # --- Retrieval ---
648
  hits = hybrid_search(question, k=k, w_tfidf=w_tfidf, w_bm25=w_bm25, w_emb=w_emb)
649
- t1_retr = time.time()
650
- latency_ms_retriever = int((t1_retr - t0_retr) * 1000)
651
-
652
  if hits is None or hits.empty:
653
- final = "No indexed PDFs found. Upload PDFs to the 'papers/' folder and reload the Space."
654
- record = {
655
- "run_id": run_id,
656
- "ts": int(time.time()*1000),
657
- "inputs": {
658
- "question": question, "top_k": int(k), "n_sentences": int(n_sentences),
659
- "w_tfidf": float(w_tfidf), "w_bm25": float(w_bm25), "w_emb": float(w_emb),
660
- "use_llm": bool(use_llm), "model": model, "temperature": float(temperature)
661
- },
662
- "retrieval": {"hits": [], "latency_ms_retriever": latency_ms_retriever},
663
- "output": {"final_answer": final, "used_sentences": []},
664
- "latency_ms_total": int((time.time()-t0_total)*1000),
665
- "openai": None
666
- }
667
- _safe_write_jsonl(LOG_PATH, record)
668
- return final
669
-
670
- # Select sentences
671
  selected = mmr_select_sentences(question, hits, top_n=int(n_sentences), pool_per_chunk=6, lambda_div=0.7)
 
 
 
672
 
673
- # Header citations: short codes only, joined by '; ' (e.g., "S55; S71; S92")
674
- header_codes = []
675
- for _, r in hits.head(6).iterrows():
676
- code = _short_doc_code(r["doc_path"])
677
- if code not in header_codes:
678
- header_codes.append(code)
679
- header_cites = "; ".join(header_codes)
680
- src_codes = set(header_codes)
681
- coverage_note = "" if len(src_codes) >= 3 else f"\n\n> Note: Only {len(src_codes)} unique source(s) contributed. Add more PDFs or increase Top-K."
682
-
683
- # Prepare retrieval list for logging (full filenames kept here)
684
- retr_list = []
685
- for _, r in hits.iterrows():
686
- retr_list.append({
687
- "doc": Path(r["doc_path"]).name,
688
- "page": _extract_page(r["text"]),
689
- "score_tfidf": float(r.get("score_tfidf", 0.0)),
690
- "score_bm25": float(r.get("score_bm25", 0.0)),
691
- "score_dense": float(r.get("score_dense", 0.0)),
692
- "combo_score": float(r.get("score", 0.0)),
693
- })
694
-
695
- # Strict quotes only (no LLM)
696
  if strict_quotes_only:
697
  if not selected:
698
- final = (
699
- "**Quoted Passages:**\n\n---\n" +
700
- "\n\n".join(hits['text'].tolist()[:2]) +
701
- f"\n\n**Citations:** {header_cites}{coverage_note}"
702
- )
703
- else:
704
- bullets = "\n- ".join(f"{s['sent']} ({s['doc']})" for s in selected)
705
- final = f"**Quoted Passages:**\n- {bullets}\n\n**Citations:** {header_cites}{coverage_note}"
706
- if include_passages:
707
- final += "\n\n---\n" + "\n\n".join(hits['text'].tolist()[:2])
708
-
709
- record = {
710
- "run_id": run_id,
711
- "ts": int(time.time()*1000),
712
- "inputs": {
713
- "question": question, "top_k": int(k), "n_sentences": int(n_sentences),
714
- "w_tfidf": float(w_tfidf), "w_bm25": float(w_bm25), "w_emb": float(w_emb),
715
- "use_llm": False, "model": None, "temperature": float(temperature)
716
- },
717
- "retrieval": {"hits": retr_list, "latency_ms_retriever": latency_ms_retriever},
718
- "output": {
719
- "final_answer": final,
720
- "used_sentences": [{"sent": s["sent"], "doc": s["doc"], "page": s["page"]} for s in selected]
721
- },
722
- "latency_ms_total": int((time.time()-t0_total)*1000),
723
- "openai": None
724
- }
725
- _safe_write_jsonl(LOG_PATH, record)
726
- return final
727
-
728
- # Extractive or LLM synthesis
729
  extractive = compose_extractive(selected)
730
- llm_usage = None
731
- llm_latency_ms = None
732
  if use_llm and selected:
733
- # Lines already carry short-code citations, e.g. "... (S92)"
734
- lines = [f"{s['sent']} ({s['doc']})" for s in selected]
735
- t0_llm = time.time()
736
- llm_text, llm_usage = synthesize_with_llm(question, lines, model=model, temperature=temperature)
737
- t1_llm = time.time()
738
- llm_latency_ms = int((t1_llm - t0_llm) * 1000)
739
-
740
  if llm_text:
741
- final = f"**Answer (LLM synthesis):** {llm_text}\n\n**Citations:** {header_cites}{coverage_note}"
742
  if include_passages:
743
- final += "\n\n---\n" + "\n\n".join(hits['text'].tolist()[:2])
744
- else:
745
- if not extractive:
746
- final = (
747
- f"**Answer:** Here are relevant passages.\n\n"
748
- f"**Citations:** {header_cites}{coverage_note}\n\n---\n" +
749
- "\n\n".join(hits['text'].tolist()[:2])
750
- )
751
- else:
752
- final = f"**Answer:** {extractive}\n\n**Citations:** {header_cites}{coverage_note}"
753
- if include_passages:
754
- final += "\n\n---\n" + "\n\n".join(hits['text'].tolist()[:2])
755
- else:
756
- if not extractive:
757
- final = (
758
- f"**Answer:** Here are relevant passages.\n\n"
759
- f"**Citations:** {header_cites}{coverage_note}\n\n---\n" +
760
- "\n\n".join(hits['text'].tolist()[:2])
761
- )
762
- else:
763
- final = f"**Answer:** {extractive}\n\n**Citations:** {header_cites}{coverage_note}"
764
- if include_passages:
765
- final += "\n\n---\n" + "\n\n".join(hits['text'].tolist()[:2])
766
-
767
- # --------- Log full run ---------
768
- prompt_toks = llm_usage.get("prompt_tokens") if llm_usage else None
769
- completion_toks = llm_usage.get("completion_tokens") if llm_usage else None
770
- cost_usd = _calc_cost_usd(prompt_toks, completion_toks)
771
-
772
- total_ms = int((time.time() - t0_total) * 1000)
773
- record = {
774
- "run_id": run_id,
775
- "ts": int(time.time()*1000),
776
- "inputs": {
777
- "question": question, "top_k": int(k), "n_sentences": int(n_sentences),
778
- "w_tfidf": float(w_tfidf), "w_bm25": float(w_bm25), "w_emb": float(w_emb),
779
- "use_llm": bool(use_llm), "model": model, "temperature": float(temperature)
780
- },
781
- "retrieval": {"hits": retr_list, "latency_ms_retriever": latency_ms_retriever},
782
- "output": {
783
- "final_answer": final,
784
- "used_sentences": [{"sent": s['sent'], "doc": s['doc'], "page": s['page']} for s in selected]
785
- },
786
- "latency_ms_total": total_ms,
787
- "latency_ms_llm": llm_latency_ms,
788
- "openai": {
789
- "prompt_tokens": prompt_toks,
790
- "completion_tokens": completion_toks,
791
- "cost_usd": cost_usd
792
- } if use_llm else None
793
- }
794
- _safe_write_jsonl(LOG_PATH, record)
795
- return final
796
 
797
  def rag_chat_fn(message, history, top_k, n_sentences, include_passages,
798
  use_llm, model_name, temperature, strict_quotes_only,
@@ -816,225 +553,24 @@ def rag_chat_fn(message, history, top_k, n_sentences, include_passages,
816
  except Exception as e:
817
  return f"RAG error: {e}"
818
 
819
- # ========================= UI (science-oriented styling) =========================
820
  CSS = """
821
- /* Science-oriented: crisp contrast + readable numerics */
822
- * {font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial;}
823
  .gradio-container {
824
- background: linear-gradient(135deg, #0b1020 0%, #0c2b1a 60%, #0a2b4d 100%) !important;
825
- }
826
- .card {background: rgba(255,255,255,0.06) !important; border: 1px solid rgba(255,255,255,0.14); border-radius: 12px;}
827
- label {color: #e8f7ff !important; text-shadow: 0 1px 0 rgba(0,0,0,0.35); cursor: pointer;}
828
- input[type="number"] {font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;}
829
-
830
- /* Checkbox clickability fixes */
831
- input[type="checkbox"], .gr-checkbox, .gr-checkbox > * { pointer-events: auto !important; }
832
- .gr-checkbox label, .gr-check-radio label { pointer-events: auto !important; cursor: pointer; }
833
- #rag-tab input[type="checkbox"] { accent-color: #60a5fa !important; }
834
-
835
- /* RAG tab styling */
836
- #rag-tab .block, #rag-tab .group, #rag-tab .accordion {
837
- background: linear-gradient(160deg, #1f2937 0%, #14532d 55%, #0b3b68 100%) !important;
838
- border-radius: 12px;
839
- border: 1px solid rgba(255,255,255,0.14);
840
- }
841
- #rag-tab input, #rag-tab textarea, #rag-tab select, #rag-tab .scroll-hide, #rag-tab .chatbot textarea {
842
- background: rgba(17, 24, 39, 0.85) !important;
843
- border: 1px solid #60a5fa !important;
844
- color: #e5f2ff !important;
845
- }
846
- #rag-tab input[type="range"] { accent-color: #22c55e !important; }
847
- #rag-tab button { border-radius: 10px !important; font-weight: 600 !important; }
848
- #rag-tab .chatbot {
849
- background: rgba(15, 23, 42, 0.6) !important;
850
- border: 1px solid rgba(148, 163, 184, 0.35) !important;
851
- }
852
- #rag-tab .message.user {
853
- background: rgba(34, 197, 94, 0.15) !important;
854
- border-left: 3px solid #22c55e !important;
855
- }
856
- #rag-tab .message.bot {
857
- background: rgba(59, 130, 246, 0.15) !important;
858
- border-left: 3px solid #60a5fa !important;
859
- color: #eef6ff !important;
860
- }
861
-
862
- /* Evaluate tab dark/high-contrast styling */
863
- #eval-tab .block, #eval-tab .group, #eval-tab .accordion {
864
- background: linear-gradient(165deg, #0a0f1f 0%, #0d1a31 60%, #0a1c2e 100%) !important;
865
- border-radius: 12px;
866
- border: 1px solid rgba(139, 197, 255, 0.28);
867
- }
868
- #eval-tab label, #eval-tab .markdown, #eval-tab .prose, #eval-tab p, #eval-tab span {
869
- color: #e6f2ff !important;
870
- }
871
- #eval-tab input, #eval-tab .gr-file, #eval-tab .scroll-hide, #eval-tab textarea, #eval-tab select {
872
- background: rgba(8, 13, 26, 0.9) !important;
873
- border: 1px solid #3b82f6 !important;
874
- color: #dbeafe !important;
875
- }
876
- #eval-tab input[type="range"] { accent-color: #22c55e !important; }
877
- #eval-tab button {
878
- border-radius: 10px !important;
879
- font-weight: 700 !important;
880
- background: #0ea5e9 !important;
881
- color: #001321 !important;
882
- border: 1px solid #7dd3fc !important;
883
- }
884
- #eval-tab .gr-json, #eval-tab .markdown pre, #eval-tab .markdown code {
885
- background: rgba(2, 6, 23, 0.85) !important;
886
- color: #e2e8f0 !important;
887
- border: 1px solid rgba(148, 163, 184, 0.3) !important;
888
- border-radius: 10px !important;
889
- }
890
-
891
- /* Predictor output emphasis */
892
- #pred-out .wrap { font-size: 20px; font-weight: 700; color: #ecfdf5; }
893
-
894
- /* Tab header: darker blue theme for all tabs */
895
- .gradio-container .tab-nav button[role="tab"] {
896
- background: #0b1b34 !important;
897
- color: #cfe6ff !important;
898
- border: 1px solid #1e3a8a !important;
899
- }
900
- .gradio-container .tab-nav button[role="tab"][aria-selected="true"] {
901
- background: #0e2a57 !important;
902
- color: #e0f2fe !important;
903
- border-color: #3b82f6 !important;
904
- }
905
-
906
- /* Evaluate tab: enforce dark-blue text for labels/marks */
907
- #eval-tab .label,
908
- #eval-tab label,
909
- #eval-tab .gr-slider .label,
910
- #eval-tab .wrap .label,
911
- #eval-tab .prose,
912
- #eval-tab .markdown,
913
- #eval-tab p,
914
- #eval-tab span {
915
- color: #cfe6ff !important;
916
- }
917
-
918
- /* Target the specific k-slider label strongly */
919
- #k-slider .label,
920
- #k-slider label,
921
- #k-slider .wrap .label {
922
- color: #cfe6ff !important;
923
- text-shadow: 0 1px 0 rgba(0,0,0,0.35);
924
- }
925
-
926
- /* Slider track/thumb (dark blue gradient + blue thumb) */
927
- #eval-tab input[type="range"] {
928
- accent-color: #3b82f6 !important;
929
- }
930
-
931
- /* WebKit */
932
- #eval-tab input[type="range"]::-webkit-slider-runnable-track {
933
- height: 6px;
934
- background: linear-gradient(90deg, #0b3b68, #1e3a8a);
935
- border-radius: 4px;
936
- }
937
- #eval-tab input[type="range"]::-webkit-slider-thumb {
938
- -webkit-appearance: none;
939
- appearance: none;
940
- margin-top: -6px;
941
- width: 18px; height: 18px;
942
- background: #1d4ed8;
943
- border: 1px solid #60a5fa;
944
- border-radius: 50%;
945
- }
946
-
947
- /* Firefox */
948
- #eval-tab input[type="range"]::-moz-range-track {
949
- height: 6px;
950
- background: linear-gradient(90deg, #0b3b68, #1e3a8a);
951
- border-radius: 4px;
952
- }
953
- #eval-tab input[type="range"]::-moz-range-thumb {
954
- width: 18px; height: 18px;
955
- background: #1d4ed8;
956
- border: 1px solid #60a5fa;
957
- border-radius: 50%;
958
- }
959
-
960
- /* ======== PATCH: Style the File + JSON outputs by ID ======== */
961
- #perq-file, #agg-file {
962
- background: rgba(8, 13, 26, 0.9) !important;
963
- border: 1px solid #3b82f6 !important;
964
- border-radius: 12px !important;
965
- padding: 8px !important;
966
- }
967
- #perq-file * , #agg-file * { color: #dbeafe !important; }
968
- #perq-file a, #agg-file a {
969
- background: #0e2a57 !important;
970
- color: #e0f2fe !important;
971
- border: 1px solid #60a5fa !important;
972
- border-radius: 8px !important;
973
- padding: 6px 10px !important;
974
- text-decoration: none !important;
975
- }
976
- #perq-file a:hover, #agg-file a:hover {
977
- background: #10356f !important;
978
- border-color: #93c5fd !important;
979
- }
980
- /* File preview wrappers (covers multiple Gradio render modes) */
981
- #perq-file .file-preview, #agg-file .file-preview,
982
- #perq-file .wrap, #agg-file .wrap {
983
- background: rgba(2, 6, 23, 0.85) !important;
984
- border-radius: 10px !important;
985
- border: 1px solid rgba(148,163,184,.3) !important;
986
- }
987
-
988
- /* JSON output: dark panel + readable text */
989
- #agg-json {
990
- background: rgba(2, 6, 23, 0.85) !important;
991
- border: 1px solid rgba(148,163,184,.35) !important;
992
- border-radius: 12px !important;
993
- padding: 8px !important;
994
- }
995
- #agg-json *, #agg-json .json, #agg-json .wrap { color: #e6f2ff !important; }
996
- #agg-json pre, #agg-json code {
997
- background: rgba(4, 10, 24, 0.9) !important;
998
- color: #e2e8f0 !important;
999
- border: 1px solid rgba(148,163,184,.35) !important;
1000
- border-radius: 10px !important;
1001
- }
1002
- /* Tree/overflow modes */
1003
- #agg-json [data-testid="json-tree"],
1004
- #agg-json [role="tree"],
1005
- #agg-json .overflow-auto {
1006
- background: rgba(4, 10, 24, 0.9) !important;
1007
- color: #e6f2ff !important;
1008
- border-radius: 10px !important;
1009
- border: 1px solid rgba(148,163,184,.35) !important;
1010
- }
1011
-
1012
- /* Eval log markdown */
1013
- #eval-log, #eval-log * { color: #cfe6ff !important; }
1014
- #eval-log pre, #eval-log code {
1015
- background: rgba(2, 6, 23, 0.85) !important;
1016
- color: #e2e8f0 !important;
1017
- border: 1px solid rgba(148,163,184,.3) !important;
1018
- border-radius: 10px !important;
1019
- }
1020
-
1021
- /* When Evaluate tab is active and JS has added .eval-active, bump contrast subtly */
1022
- #eval-tab.eval-active .block,
1023
- #eval-tab.eval-active .group {
1024
- border-color: #60a5fa !important;
1025
- }
1026
- #eval-tab.eval-active .label {
1027
- color: #e6f2ff !important;
1028
  }
 
 
 
1029
  """
1030
 
1031
  theme = gr.themes.Soft(
1032
  primary_hue="blue",
1033
  neutral_hue="green"
1034
  ).set(
1035
- body_background_fill="#0b1020",
1036
  body_text_color="#e0f2fe",
1037
- input_background_fill="#0f172a",
1038
  input_border_color="#1e40af",
1039
  button_primary_background_fill="#2563eb",
1040
  button_primary_text_color="#ffffff",
@@ -1043,37 +579,12 @@ theme = gr.themes.Soft(
1043
  )
1044
 
1045
  with gr.Blocks(css=CSS, theme=theme, fill_height=True) as demo:
1046
- # Optional: JS to toggle .eval-active when Evaluate tab selected
1047
- gr.HTML("""
1048
- <script>
1049
- (function(){
1050
- const applyEvalActive = () => {
1051
- const selected = document.querySelector('.tab-nav button[role="tab"][aria-selected="true"]');
1052
- const evalPanel = document.querySelector('#eval-tab');
1053
- if (!evalPanel) return;
1054
- if (selected && /Evaluate/.test(selected.textContent)) {
1055
- evalPanel.classList.add('eval-active');
1056
- } else {
1057
- evalPanel.classList.remove('eval-active');
1058
- }
1059
- };
1060
- document.addEventListener('click', function(e) {
1061
- if (e.target && e.target.getAttribute('role') === 'tab') {
1062
- setTimeout(applyEvalActive, 50);
1063
- }
1064
- }, true);
1065
- document.addEventListener('DOMContentLoaded', applyEvalActive);
1066
- setTimeout(applyEvalActive, 300);
1067
- })();
1068
- </script>
1069
- """)
1070
-
1071
  gr.Markdown(
1072
  "<h1 style='margin:0'>Self-Sensing Concrete Assistant</h1>"
1073
  "<p style='opacity:.9'>"
1074
- "Left: ML prediction for Stress Gauge Factor (original scale, MPa<sup>-1</sup>). "
1075
- "Right: Literature Q&A via Hybrid RAG (BM25 + TF-IDF + optional dense) with MMR sentence selection. "
1076
- "Answers cite short document codes (e.g., <code>S71</code>, <code>S92</code>)."
1077
  "</p>"
1078
  )
1079
 
@@ -1083,27 +594,27 @@ with gr.Blocks(css=CSS, theme=theme, fill_height=True) as demo:
1083
  with gr.Row():
1084
  with gr.Column(scale=7):
1085
  with gr.Accordion("Primary conductive filler", open=True, elem_classes=["card"]):
1086
- f1_type = gr.Textbox(label="Filler 1 Type *", placeholder="e.g., CNT, Graphite, Steel fiber")
1087
- f1_diam = gr.Number(label="Filler 1 Diameter (µm) *")
1088
- f1_len = gr.Number(label="Filler 1 Length (mm) *")
1089
- cf_conc = gr.Number(label=f"{CF_COL} *", info="Weight percent of total binder")
1090
- f1_dim = gr.Dropdown(DIM_CHOICES, value=CANON_NA, label="Filler 1 Dimensionality *")
1091
 
1092
  with gr.Accordion("Secondary filler (optional)", open=False, elem_classes=["card"]):
1093
  f2_type = gr.Textbox(label="Filler 2 Type", placeholder="Optional")
1094
  f2_diam = gr.Number(label="Filler 2 Diameter (µm)")
1095
  f2_len = gr.Number(label="Filler 2 Length (mm)")
1096
- f2_dim = gr.Dropdown(DIM_CHOICES, value=CANON_NA, label="Filler 2 Dimensionality")
1097
 
1098
  with gr.Accordion("Mix design & specimen", open=False, elem_classes=["card"]):
1099
- spec_vol = gr.Number(label="Specimen Volume (mm3) *")
1100
- probe_cnt = gr.Number(label="Probe Count *")
1101
- probe_mat = gr.Textbox(label="Probe Material *", placeholder="e.g., Copper, Silver paste")
1102
- wb = gr.Number(label="W/B *")
1103
- sb = gr.Number(label="S/B *")
1104
- gauge_len = gr.Number(label="Gauge Length (mm) *")
1105
- curing = gr.Textbox(label="Curing Condition *", placeholder="e.g., 28d water, 20°C")
1106
- n_fillers = gr.Number(label="Number of Fillers *")
1107
 
1108
  with gr.Accordion("Processing", open=False, elem_classes=["card"]):
1109
  dry_temp = gr.Number(label="Drying Temperature (°C)")
@@ -1111,14 +622,13 @@ with gr.Blocks(css=CSS, theme=theme, fill_height=True) as demo:
1111
 
1112
  with gr.Accordion("Mechanical & electrical loading", open=False, elem_classes=["card"]):
1113
  load_rate = gr.Number(label="Loading Rate (MPa/s)")
1114
- E_mod = gr.Number(label="Modulus of Elasticity (GPa) *")
1115
- current = gr.Dropdown(CURRENT_CHOICES, value=CANON_NA, label="Current Type")
1116
  voltage = gr.Number(label="Applied Voltage (V)")
1117
 
1118
  with gr.Column(scale=5):
1119
  with gr.Group(elem_classes=["card"]):
1120
- out_pred = gr.Number(label="Predicted Stress GF (MPa-1)", value=0.0, precision=6, elem_id="pred-out")
1121
- gr.Markdown(f"<small>{MODEL_STATUS}</small>")
1122
  with gr.Row():
1123
  btn_pred = gr.Button("Predict", variant="primary")
1124
  btn_clear = gr.Button("Clear")
@@ -1126,14 +636,14 @@ with gr.Blocks(css=CSS, theme=theme, fill_height=True) as demo:
1126
 
1127
  with gr.Accordion("About this model", open=False, elem_classes=["card"]):
1128
  gr.Markdown(
1129
- "- Pipeline: ColumnTransformer (RobustScaler + OneHot) XGBoost\n"
1130
- "- Target: Stress GF (MPa<sup>-1</sup>) on original scale (model may train on log1p; saved flag used at inference).\n"
1131
  "- Missing values are safely imputed per-feature.\n"
1132
  "- Trained columns:\n"
1133
- f" `{', '.join(MAIN_VARIABLES)}`",
1134
- elem_classes=["prose"]
1135
  )
1136
 
 
1137
  inputs_in_order = [
1138
  f1_type, f1_diam, f1_len, cf_conc,
1139
  f1_dim, f2_type, f2_diam, f2_len,
@@ -1148,108 +658,38 @@ with gr.Blocks(css=CSS, theme=theme, fill_height=True) as demo:
1148
  return predict_fn(**data)
1149
 
1150
  btn_pred.click(_predict_wrapper, inputs=inputs_in_order, outputs=out_pred)
1151
- btn_clear.click(lambda: _clear_all(), inputs=None, outputs=inputs_in_order).then(lambda: 0.0, outputs=out_pred)
1152
  btn_demo.click(lambda: _fill_example(), inputs=None, outputs=inputs_in_order)
1153
 
1154
  # ------------------------- Literature Tab -------------------------
1155
- with gr.Tab("📚 Ask the Literature (Hybrid RAG + MMR)", elem_id="rag-tab"):
1156
- pdf_count = len(list(LOCAL_PDF_DIR.glob("**/*.pdf")))
1157
  gr.Markdown(
1158
- f"Using local folder <code>papers/</code> **{pdf_count} PDF(s)** indexed. "
1159
- "Upload more PDFs and reload the Space to expand coverage. "
1160
- "Answers cite short document codes such as <code>S71</code>, <code>S92</code>."
1161
  )
1162
  with gr.Row():
1163
  top_k = gr.Slider(5, 12, value=8, step=1, label="Top-K chunks")
1164
  n_sentences = gr.Slider(2, 6, value=4, step=1, label="Answer length (sentences)")
1165
- include_passages = gr.Checkbox(value=False, label="Include supporting passages", interactive=True)
1166
-
1167
  with gr.Accordion("Retriever weights (advanced)", open=False):
1168
  w_tfidf = gr.Slider(0.0, 1.0, value=W_TFIDF_DEFAULT, step=0.05, label="TF-IDF weight")
1169
  w_bm25 = gr.Slider(0.0, 1.0, value=W_BM25_DEFAULT, step=0.05, label="BM25 weight")
1170
- w_emb = gr.Slider(0.0, 1.0, value=(0.0 if not USE_DENSE else 0.40), step=0.05, label="Dense weight (set 0 if disabled)")
1171
-
1172
- # Hidden states (unchanged)
1173
- state_use_llm = gr.State(LLM_AVAILABLE)
1174
- state_model_name = gr.State(os.getenv("OPENAI_MODEL", OPENAI_MODEL))
1175
- state_temperature = gr.State(0.2)
1176
- state_strict = gr.State(False)
1177
-
1178
  gr.ChatInterface(
1179
  fn=rag_chat_fn,
1180
- additional_inputs=[
1181
- top_k, n_sentences, include_passages,
1182
- state_use_llm, state_model_name, state_temperature, state_strict,
1183
- w_tfidf, w_bm25, w_emb
1184
- ],
1185
  title="Literature Q&A",
1186
- description="Hybrid retrieval with diversity. Answers carry inline short-code citations (e.g., (S92), (S71))."
1187
  )
1188
 
1189
- # ====== Evaluate (Gold vs Logs) ======
1190
- with gr.Tab("📏 Evaluate (Gold vs Logs)", elem_id="eval-tab"):
1191
- gr.Markdown("Upload your **gold.csv** and compute metrics against the app logs.")
1192
- with gr.Row():
1193
- gold_file = gr.File(label="gold.csv", file_types=[".csv"], interactive=True)
1194
- k_slider = gr.Slider(3, 12, value=8, step=1, label="k for Hit/Recall/nDCG", elem_id="k-slider")
1195
- with gr.Row():
1196
- btn_eval = gr.Button("Compute Metrics", variant="primary")
1197
- with gr.Row():
1198
- out_perq = gr.File(label="Per-question metrics (CSV)", elem_id="perq-file")
1199
- out_agg = gr.File(label="Aggregate metrics (JSON)", elem_id="agg-file")
1200
- out_json = gr.JSON(label="Aggregate summary", elem_id="agg-json")
1201
- out_log = gr.Markdown(label="Run log", elem_id="eval-log")
1202
-
1203
- def _run_eval_inproc(gold_path: str, k: int = 8):
1204
- import json as _json
1205
- out_dir = str(ARTIFACT_DIR)
1206
- logs = str(LOG_PATH)
1207
- cmd = [
1208
- sys.executable, "rag_eval_metrics.py",
1209
- "--gold_csv", gold_path,
1210
- "--logs_jsonl", logs,
1211
- "--k", str(k),
1212
- "--out_dir", out_dir
1213
- ]
1214
- try:
1215
- p = subprocess.run(cmd, capture_output=True, text=True, check=False)
1216
- stdout = p.stdout or ""
1217
- stderr = p.stderr or ""
1218
- perq = ARTIFACT_DIR / "metrics_per_question.csv"
1219
- agg = ARTIFACT_DIR / "metrics_aggregate.json"
1220
- agg_json = {}
1221
- if agg.exists():
1222
- agg_json = _json.loads(agg.read_text(encoding="utf-8"))
1223
- report = "```\n" + (stdout.strip() or "(no stdout)") + ("\n" + stderr.strip() if stderr else "") + "\n```"
1224
- return (str(perq) if perq.exists() else None,
1225
- str(agg) if agg.exists() else None,
1226
- agg_json,
1227
- report)
1228
- except Exception as e:
1229
- return (None, None, {}, f"**Eval error:** {e}")
1230
-
1231
- def _eval_wrapper(gf, k):
1232
- from pathlib import Path as _Path
1233
- if gf is None:
1234
- default_gold = _Path("gold.csv")
1235
- if not default_gold.exists():
1236
- return None, None, {}, "**No gold.csv provided or found in repo root.**"
1237
- gold_path = str(default_gold)
1238
- else:
1239
- gold_path = gf.name
1240
- return _run_eval_inproc(gold_path, int(k))
1241
-
1242
- btn_eval.click(_eval_wrapper, inputs=[gold_file, k_slider],
1243
- outputs=[out_perq, out_agg, out_json, out_log])
1244
-
1245
  # ------------- Launch -------------
1246
  if __name__ == "__main__":
 
1247
  demo.queue().launch()
1248
-
1249
- # After launch: export a simple list of PDFs as paper_list.csv
1250
- import os as _os
1251
- import pandas as _pd
1252
- folder = "papers"
1253
- files = sorted(_os.listdir(folder)) if _os.path.exists(folder) else []
1254
- _pd.DataFrame({"doc": files}).to_csv("paper_list.csv", index=False)
1255
- print("✅ Saved paper_list.csv with", len(files), "papers")
 
1
+ # vmm
2
  # Self-Sensing Concrete Assistant — Predictor (XGB) + Hybrid RAG
3
+ # - Predictor tab: identical behavior to your "second code"
4
+ # - Literature tab: from your "first code" (Hybrid RAG + MMR)
5
+ # - Hugging Face friendly: online PDF fetching OFF by default
 
 
 
 
6
  # ================================================================
7
 
8
  # ---------------------- Runtime flags (HF-safe) ----------------------
 
12
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
13
 
14
  # ------------------------------- Imports ------------------------------
15
+ import re, time, joblib, warnings, json
16
  from pathlib import Path
17
+ from typing import List, Dict, Any
18
 
19
  import numpy as np
20
  import pandas as pd
 
35
  BM25Okapi = None
36
  print("rank_bm25 not installed; BM25 disabled (TF-IDF still works).")
37
 
38
+ # Optional OpenAI (for LLM paraphrase)
39
  OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
40
+ OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-4o-mini").strip().strip('"').strip("'")
41
+
42
  try:
43
  from openai import OpenAI
44
  except Exception:
45
  OpenAI = None
46
 
47
+ print("openAI: ", OpenAI)
 
48
 
49
+ # ========================= Predictor (kept same as 2nd) =========================
50
  CF_COL = "Conductive Filler Conc. (wt%)"
51
  TARGET_COL = "Stress GF (MPa-1)"
 
52
 
53
  MAIN_VARIABLES = [
54
  "Filler 1 Type",
 
105
  "Current Type"
106
  }
107
 
108
+ DIM_CHOICES = ["0D", "1D", "2D", "3D", "NA"]
109
+ CURRENT_CHOICES = ["DC", "AC", "NA"]
110
 
111
  MODEL_CANDIDATES = [
112
  "stress_gf_xgb.joblib",
113
  "models/stress_gf_xgb.joblib",
114
  "/home/user/app/stress_gf_xgb.joblib",
 
115
  ]
116
 
117
+ def _load_model_or_error():
118
+ for p in MODEL_CANDIDATES:
 
 
 
 
 
119
  if os.path.exists(p):
120
  try:
121
+ return joblib.load(p)
 
 
 
122
  except Exception as e:
123
+ return f"Could not load model from {p}: {e}"
124
+ return ("Model file not found. Upload your trained pipeline as "
125
+ "stress_gf_xgb.joblib (or put it in models/).")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
  def _coerce_to_row(form_dict: dict) -> pd.DataFrame:
128
  row = {}
129
  for col in MAIN_VARIABLES:
130
  v = form_dict.get(col, None)
131
  if col in NUMERIC_COLS:
132
+ if v in ("", None):
133
+ row[col] = np.nan
134
+ else:
135
+ try:
136
+ row[col] = float(v)
137
+ except Exception:
138
+ row[col] = np.nan
139
  else:
140
+ row[col] = "" if v in (None, "NA") else str(v).strip()
 
141
  return pd.DataFrame([row], columns=MAIN_VARIABLES)
142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  def predict_fn(**kwargs):
144
+ mdl = _load_model_or_error()
145
+ if isinstance(mdl, str):
146
+ return mdl
 
 
 
 
 
147
  X_new = _coerce_to_row(kwargs)
 
148
  try:
149
+ y_log = mdl.predict(X_new) # model predicts log1p(target)
150
+ y = float(np.expm1(y_log)[0]) # back to original scale MPa^-1
151
+ if -1e-10 < y < 0:
152
+ y = 0.0
153
+ return y
 
 
154
  except Exception as e:
155
+ return f"Prediction error: {e}"
 
 
156
 
157
  EXAMPLE = {
158
  "Filler 1 Type": "CNT",
 
161
  "Filler 1 Length (mm)": 1.2,
162
  CF_COL: 0.5,
163
  "Filler 2 Type": "",
164
+ "Filler 2 Dimensionality": "NA",
165
  "Filler 2 Diameter (µm)": None,
166
  "Filler 2 Length (mm)": None,
167
  "Specimen Volume (mm3)": 1000,
 
189
  if col in NUMERIC_COLS:
190
  cleared.append(None)
191
  elif col in {"Filler 1 Dimensionality", "Filler 2 Dimensionality"}:
192
+ cleared.append("NA")
193
  elif col == "Current Type":
194
+ cleared.append("NA")
195
  else:
196
  cleared.append("")
197
  return cleared
198
 
199
+ # ========================= Hybrid RAG (from 1st code) =========================
200
+ # Configuration
201
  ARTIFACT_DIR = Path("rag_artifacts"); ARTIFACT_DIR.mkdir(exist_ok=True)
202
  TFIDF_VECT_PATH = ARTIFACT_DIR / "tfidf_vectorizer.joblib"
203
  TFIDF_MAT_PATH = ARTIFACT_DIR / "tfidf_matrix.joblib"
 
205
  EMB_NPY_PATH = ARTIFACT_DIR / "chunk_embeddings.npy"
206
  RAG_META_PATH = ARTIFACT_DIR / "chunks.parquet"
207
 
208
+ # PDF source (HF-safe: rely on local /papers by default)
209
+ LOCAL_PDF_DIR = Path("./literature_pdfs"); LOCAL_PDF_DIR.mkdir(exist_ok=True)
210
  USE_ONLINE_SOURCES = os.getenv("USE_ONLINE_SOURCES", "false").lower() == "true"
211
 
212
+ # Retrieval weights
213
  W_TFIDF_DEFAULT = 0.50 if not USE_DENSE else 0.30
214
  W_BM25_DEFAULT = 0.50 if not USE_DENSE else 0.30
215
+ W_EMB_DEFAULT = 0.00 if not USE_DENSE else 0.40
216
 
217
+ # Simple text processing
218
  _SENT_SPLIT_RE = re.compile(r"(?<=[.!?])\s+|\n+")
219
  TOKEN_RE = re.compile(r"[A-Za-z0-9_#+\-/\.%]+")
220
  def sent_split(text: str) -> List[str]:
 
223
  def tokenize(text: str) -> List[str]:
224
  return [t.lower() for t in TOKEN_RE.findall(text)]
225
 
226
+ # PDF text extraction (PyMuPDF preferred; pypdf fallback)
227
  def _extract_pdf_text(pdf_path: Path) -> str:
228
  try:
229
  import fitz
 
265
  USE_DENSE = False
266
  return None
267
 
268
+ # Build or load index
269
  def build_or_load_hybrid(pdf_dir: Path):
 
270
  have_cache = (TFIDF_VECT_PATH.exists() and TFIDF_MAT_PATH.exists()
271
  and RAG_META_PATH.exists()
272
  and (BM25_TOK_PATH.exists() or BM25Okapi is None)
 
290
  rows.append({"doc_path": str(pdf), "chunk_id": i, "text": ch})
291
  all_tokens.append(tokenize(ch))
292
  if not rows:
293
+ # create empty stub to avoid crashes; UI will message user to upload PDFs
294
  meta = pd.DataFrame(columns=["doc_path", "chunk_id", "text"])
295
  vectorizer = None; X_tfidf = None; emb = None; all_tokens = None
296
  return vectorizer, X_tfidf, meta, all_tokens, emb
297
 
298
  meta = pd.DataFrame(rows)
299
+
300
  from sklearn.feature_extraction.text import TfidfVectorizer
301
  vectorizer = TfidfVectorizer(
302
  ngram_range=(1,2),
 
320
  print("Dense embedding failed:", e)
321
  emb = None
322
 
323
+ # Save artifacts
324
  joblib.dump(vectorizer, TFIDF_VECT_PATH)
325
  joblib.dump(X_tfidf, TFIDF_MAT_PATH)
326
  if BM25Okapi is not None:
327
  joblib.dump(all_tokens, BM25_TOK_PATH)
328
  meta.to_parquet(RAG_META_PATH, index=False)
329
+
330
  return vectorizer, X_tfidf, meta, all_tokens, emb
331
 
332
  tfidf_vectorizer, tfidf_matrix, rag_meta, bm25_tokens, emb_matrix = build_or_load_hybrid(LOCAL_PDF_DIR)
 
334
  st_query_model = _safe_init_st_model(os.getenv("EMB_MODEL_NAME", "sentence-transformers/all-MiniLM-L6-v2"))
335
 
336
  def _extract_page(text_chunk: str) -> str:
 
337
  m = list(re.finditer(r"\[\[PAGE=(\d+)\]\]", text_chunk or ""))
338
  return (m[-1].group(1) if m else "?")
339
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  def hybrid_search(query: str, k=8, w_tfidf=W_TFIDF_DEFAULT, w_bm25=W_BM25_DEFAULT, w_emb=W_EMB_DEFAULT):
341
  if rag_meta is None or rag_meta.empty:
342
  return pd.DataFrame()
 
363
 
364
  # BM25 scores
365
  if bm25 is not None:
366
+ q_tokens = [t.lower() for t in re.findall(r"[A-Za-z0-9_#+\-/\.%]+", query)]
367
  bm25_scores = np.array(bm25.get_scores(q_tokens), dtype=float)
368
  else:
369
  bm25_scores = np.zeros(len(rag_meta), dtype=float); w_bm25 = 0.0
 
395
  return [s for s in sents if 6 <= len(s.split()) <= 60]
396
 
397
  def mmr_select_sentences(question: str, hits: pd.DataFrame, top_n=4, pool_per_chunk=6, lambda_div=0.7):
 
 
 
 
 
 
 
398
  pool = []
399
  for _, row in hits.iterrows():
400
+ doc = Path(row["doc_path"]).name
401
  page = _extract_page(row["text"])
402
+ for s in split_sentences(row["text"])[:pool_per_chunk]:
403
+ pool.append({"sent": s, "doc": doc, "page": page})
 
 
 
 
404
  if not pool:
405
  return []
406
 
 
407
  sent_texts = [p["sent"] for p in pool]
408
+
409
+ # Embedding-based relevance if available, else TF-IDF
410
  use_dense = USE_DENSE and st_query_model is not None
411
+ if use_dense:
412
+ try:
413
  from sklearn.preprocessing import normalize as sk_normalize
414
+ texts = [question] + sent_texts
415
+ enc = st_query_model.encode(texts, convert_to_numpy=True)
416
  q_vec = sk_normalize(enc[:1])[0]
417
  S = sk_normalize(enc[1:])
418
  rel = (S @ q_vec)
419
  def sim_fn(i, j): return float(S[i] @ S[j])
420
+ except Exception:
421
+ use_dense = False
 
 
 
 
 
 
 
 
 
 
422
 
423
+ if not use_dense:
424
+ from sklearn.feature_extraction.text import TfidfVectorizer
425
+ vect = TfidfVectorizer().fit(sent_texts + [question])
426
+ Q = vect.transform([question]); S = vect.transform(sent_texts)
427
+ rel = (S @ Q.T).toarray().ravel()
428
+ def sim_fn(i, j): return float((S[i] @ S[j].T).toarray()[0, 0])
429
 
430
+ selected, selected_idx = [], []
431
  remain = list(range(len(pool)))
 
 
432
  first = int(np.argmax(rel))
433
+ selected.append(pool[first]); selected_idx.append(first); remain.remove(first)
 
 
434
 
435
+ while len(selected) < top_n and remain:
 
 
436
  cand_scores = []
437
  for i in remain:
438
+ sim_to_sel = max(sim_fn(i, j) for j in selected_idx) if selected_idx else 0.0
439
+ score = lambda_div * rel[i] - (1 - lambda_div) * sim_to_sel
440
  cand_scores.append((score, i))
 
 
441
  cand_scores.sort(reverse=True)
442
+ best_i = cand_scores[0][1]
443
+ selected.append(pool[best_i]); selected_idx.append(best_i); remain.remove(best_i)
 
 
 
444
  return selected
445
 
446
  def compose_extractive(selected: List[Dict[str, Any]]) -> str:
447
  if not selected:
448
  return ""
449
+ return " ".join(f"{s['sent']} ({s['doc']}, p.{s['page']})" for s in selected)
 
 
 
 
 
 
450
 
451
+ def synthesize_with_llm(question: str, sentence_lines: List[str], model: str = None, temperature: float = 0.2) -> str:
452
+ if OPENAI_API_KEY is None or OpenAI is None:
 
 
 
 
 
 
 
453
  return None
454
+ print("calling LLM api")
 
 
 
 
 
455
  client = OpenAI(api_key=OPENAI_API_KEY)
456
  model = model or OPENAI_MODEL
457
+ print("using: ", model)
458
  SYSTEM_PROMPT = (
459
  "You are a scientific assistant for self-sensing cementitious materials.\n"
460
  "Answer STRICTLY using the provided sentences.\n"
461
  "Do not invent facts. Keep it concise (3–6 sentences).\n"
462
+ "Retain inline citations like (Doc.pdf, p.X) exactly as given."
463
  )
464
  user_prompt = (
465
  f"Question: {question}\n\n"
 
475
  ],
476
  temperature=temperature,
477
  )
478
+ print(resp.output_text)
479
+ return getattr(resp, "output_text", None) or str(resp)
480
+ except Exception as e:
481
+ print("error in LLM synthesis:", e)
482
+ return None
483
+
 
 
 
 
 
 
 
484
 
485
  def rag_reply(
486
  question: str,
487
  k: int = 8,
488
  n_sentences: int = 4,
489
  include_passages: bool = False,
490
+ use_llm: bool = True,
491
+ model: str = "gpt-4o-mini",
492
  temperature: float = 0.2,
493
  strict_quotes_only: bool = False,
494
  w_tfidf: float = W_TFIDF_DEFAULT,
495
  w_bm25: float = W_BM25_DEFAULT,
496
  w_emb: float = W_EMB_DEFAULT
497
  ) -> str:
 
 
 
 
 
498
  hits = hybrid_search(question, k=k, w_tfidf=w_tfidf, w_bm25=w_bm25, w_emb=w_emb)
 
 
 
499
  if hits is None or hits.empty:
500
+ return "No indexed PDFs found. Upload PDFs to the 'papers/' folder and reload the Space."
501
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
502
  selected = mmr_select_sentences(question, hits, top_n=int(n_sentences), pool_per_chunk=6, lambda_div=0.7)
503
+ header_cites = "; ".join(f"{Path(r['doc_path']).name} (p.{_extract_page(r['text'])})" for _, r in hits.head(6).iterrows())
504
+ srcs = {Path(r['doc_path']).name for _, r in hits.iterrows()}
505
+ coverage_note = "" if len(srcs) >= 3 else f"\n\n> Note: Only {len(srcs)} unique source(s) contributed. Add more PDFs or increase Top-K."
506
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
507
  if strict_quotes_only:
508
  if not selected:
509
+ return f"**Quoted Passages:**\n\n---\n" + "\n\n".join(hits['text'].tolist()[:2]) + f"\n\n**Citations:** {header_cites}{coverage_note}"
510
+ msg = "**Quoted Passages:**\n- " + "\n- ".join(f"{s['sent']} ({s['doc']}, p.{s['page']})" for s in selected)
511
+ msg += f"\n\n**Citations:** {header_cites}{coverage_note}"
512
+ if include_passages:
513
+ msg += "\n\n---\n" + "\n\n".join(hits['text'].tolist()[:2])
514
+ return msg
515
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
516
  extractive = compose_extractive(selected)
 
 
517
  if use_llm and selected:
518
+ lines = [f"{s['sent']} ({s['doc']}, p.{s['page']})" for s in selected]
519
+ llm_text = synthesize_with_llm(question, lines, model=model, temperature=temperature)
 
 
 
 
 
520
  if llm_text:
521
+ msg = f"**Answer (LLM synthesis):** {llm_text}\n\n**Citations:** {header_cites}{coverage_note}"
522
  if include_passages:
523
+ msg += "\n\n---\n" + "\n\n".join(hits['text'].tolist()[:2])
524
+ return msg
525
+
526
+ if not extractive:
527
+ return f"**Answer:** Here are relevant passages.\n\n**Citations:** {header_cites}{coverage_note}\n\n---\n" + "\n\n".join(hits['text'].tolist()[:2])
528
+
529
+ msg = f"**Answer:** {extractive}\n\n**Citations:** {header_cites}{coverage_note}"
530
+ if include_passages:
531
+ msg += "\n\n---\n" + "\n\n".join(hits['text'].tolist()[:2])
532
+ return msg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533
 
534
  def rag_chat_fn(message, history, top_k, n_sentences, include_passages,
535
  use_llm, model_name, temperature, strict_quotes_only,
 
553
  except Exception as e:
554
  return f"RAG error: {e}"
555
 
556
+ # ========================= UI (predictor styling kept) =========================
557
  CSS = """
558
+ /* Blue to green gradient background */
 
559
  .gradio-container {
560
+ background: linear-gradient(135deg, #1e3a8a 0%, #166534 60%, #15803d 100%) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
  }
562
+ * {font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial;}
563
+ .card {background: rgba(255,255,255,0.07) !important; border: 1px solid rgba(255,255,255,0.12);}
564
+ label.svelte-1ipelgc {color: #e0f2fe !important;}
565
  """
566
 
567
  theme = gr.themes.Soft(
568
  primary_hue="blue",
569
  neutral_hue="green"
570
  ).set(
571
+ body_background_fill="#1e3a8a",
572
  body_text_color="#e0f2fe",
573
+ input_background_fill="#172554",
574
  input_border_color="#1e40af",
575
  button_primary_background_fill="#2563eb",
576
  button_primary_text_color="#ffffff",
 
579
  )
580
 
581
  with gr.Blocks(css=CSS, theme=theme, fill_height=True) as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
582
  gr.Markdown(
583
  "<h1 style='margin:0'>Self-Sensing Concrete Assistant</h1>"
584
  "<p style='opacity:.9'>"
585
+ "Left tab: ML prediction for Stress Gauge Factor (kept identical to your deployed predictor). "
586
+ "Right tab: Literature Q&A via Hybrid RAG (BM25 + TF-IDF + optional dense) with MMR sentence selection. "
587
+ "Upload PDFs into <code>papers/</code> in your Space repo."
588
  "</p>"
589
  )
590
 
 
594
  with gr.Row():
595
  with gr.Column(scale=7):
596
  with gr.Accordion("Primary conductive filler", open=True, elem_classes=["card"]):
597
+ f1_type = gr.Textbox(label="Filler 1 Type", placeholder="e.g., CNT, Graphite, Steel fiber")
598
+ f1_diam = gr.Number(label="Filler 1 Diameter (µm)")
599
+ f1_len = gr.Number(label="Filler 1 Length (mm)")
600
+ cf_conc = gr.Number(label=f"{CF_COL}", info="Weight percent of total binder")
601
+ f1_dim = gr.Dropdown(DIM_CHOICES, value="NA", label="Filler 1 Dimensionality")
602
 
603
  with gr.Accordion("Secondary filler (optional)", open=False, elem_classes=["card"]):
604
  f2_type = gr.Textbox(label="Filler 2 Type", placeholder="Optional")
605
  f2_diam = gr.Number(label="Filler 2 Diameter (µm)")
606
  f2_len = gr.Number(label="Filler 2 Length (mm)")
607
+ f2_dim = gr.Dropdown(DIM_CHOICES, value="NA", label="Filler 2 Dimensionality")
608
 
609
  with gr.Accordion("Mix design & specimen", open=False, elem_classes=["card"]):
610
+ spec_vol = gr.Number(label="Specimen Volume (mm3)")
611
+ probe_cnt = gr.Number(label="Probe Count")
612
+ probe_mat = gr.Textbox(label="Probe Material", placeholder="e.g., Copper, Silver paste")
613
+ wb = gr.Number(label="W/B")
614
+ sb = gr.Number(label="S/B")
615
+ gauge_len = gr.Number(label="Gauge Length (mm)")
616
+ curing = gr.Textbox(label="Curing Condition", placeholder="e.g., 28d water, 20°C")
617
+ n_fillers = gr.Number(label="Number of Fillers")
618
 
619
  with gr.Accordion("Processing", open=False, elem_classes=["card"]):
620
  dry_temp = gr.Number(label="Drying Temperature (°C)")
 
622
 
623
  with gr.Accordion("Mechanical & electrical loading", open=False, elem_classes=["card"]):
624
  load_rate = gr.Number(label="Loading Rate (MPa/s)")
625
+ E_mod = gr.Number(label="Modulus of Elasticity (GPa)")
626
+ current = gr.Dropdown(CURRENT_CHOICES, value="NA", label="Current Type")
627
  voltage = gr.Number(label="Applied Voltage (V)")
628
 
629
  with gr.Column(scale=5):
630
  with gr.Group(elem_classes=["card"]):
631
+ out_pred = gr.Number(label="Predicted Stress GF (MPa-1)", precision=6)
 
632
  with gr.Row():
633
  btn_pred = gr.Button("Predict", variant="primary")
634
  btn_clear = gr.Button("Clear")
 
636
 
637
  with gr.Accordion("About this model", open=False, elem_classes=["card"]):
638
  gr.Markdown(
639
+ "- Pipeline: ColumnTransformer -> (RobustScaler + OneHot) -> XGBoost\n"
640
+ "- Target: Stress GF (MPa^-1) on original scale (model trains on log1p).\n"
641
  "- Missing values are safely imputed per-feature.\n"
642
  "- Trained columns:\n"
643
+ f" `{', '.join(MAIN_VARIABLES)}`"
 
644
  )
645
 
646
+ # Wire predictor buttons
647
  inputs_in_order = [
648
  f1_type, f1_diam, f1_len, cf_conc,
649
  f1_dim, f2_type, f2_diam, f2_len,
 
658
  return predict_fn(**data)
659
 
660
  btn_pred.click(_predict_wrapper, inputs=inputs_in_order, outputs=out_pred)
661
+ btn_clear.click(lambda: _clear_all(), inputs=None, outputs=inputs_in_order)
662
  btn_demo.click(lambda: _fill_example(), inputs=None, outputs=inputs_in_order)
663
 
664
  # ------------------------- Literature Tab -------------------------
665
+ with gr.Tab("📚 Ask the Literature (Hybrid RAG + MMR)"):
 
666
  gr.Markdown(
667
+ "Upload PDFs into the repository folder <code>papers/</code> then reload the Space. "
668
+ "Answers cite (Doc.pdf, p.X). Toggle strict quotes or optional LLM paraphrasing."
 
669
  )
670
  with gr.Row():
671
  top_k = gr.Slider(5, 12, value=8, step=1, label="Top-K chunks")
672
  n_sentences = gr.Slider(2, 6, value=4, step=1, label="Answer length (sentences)")
673
+ include_passages = gr.Checkbox(value=False, label="Include supporting passages")
 
674
  with gr.Accordion("Retriever weights (advanced)", open=False):
675
  w_tfidf = gr.Slider(0.0, 1.0, value=W_TFIDF_DEFAULT, step=0.05, label="TF-IDF weight")
676
  w_bm25 = gr.Slider(0.0, 1.0, value=W_BM25_DEFAULT, step=0.05, label="BM25 weight")
677
+ w_emb = gr.Slider(0.0, 1.0, value=W_EMB_DEFAULT, step=0.05, label="Dense weight (set 0 if disabled)")
678
+ with gr.Accordion("LLM & Controls", open=False):
679
+ strict_quotes_only = gr.Checkbox(value=False, label="Strict quotes only (no paraphrasing)")
680
+ use_llm = gr.Checkbox(value=True, label="Use LLM to paraphrase selected sentences")
681
+ model_name = gr.Textbox(value=os.getenv("OPENAI_MODEL", OPENAI_MODEL),
682
+ label="LLM model", placeholder="e.g., gpt-5 or gpt-5-mini")
683
+ temperature = gr.Slider(0.0, 1.0, value=0.2, step=0.05, label="Temperature")
 
684
  gr.ChatInterface(
685
  fn=rag_chat_fn,
686
+ additional_inputs=[top_k, n_sentences, include_passages, use_llm, model_name,
687
+ temperature, strict_quotes_only, w_tfidf, w_bm25, w_emb],
 
 
 
688
  title="Literature Q&A",
689
+ description="Hybrid retrieval with diversity. Answers carry inline (Doc, p.X) citations. Toggle strict/LLM modes."
690
  )
691
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
692
  # ------------- Launch -------------
693
  if __name__ == "__main__":
694
+ # queue() helps HF Spaces with concurrency; show_error suggests upload PDFs if none
695
  demo.queue().launch()
 
 
 
 
 
 
 
 
{papers → literature_pdfs}/Carbon fiber reinforced cement improved by using silane-treated carbon fibers.pdf RENAMED
File without changes
{papers → literature_pdfs}/Silane-treated carbon fiber for reinforcing cement.pdf RENAMED
File without changes
papers/1-s2.0-S095006181732278X-main.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:e6ac4d8d3c2572eab3e5b721e0520656699b5b2e49e12f51cc52ef41d7ac5e6f
3
- size 2770836
 
 
 
 
papers/1-s2.0-S0950061820330786-main.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:3e0545545fe157b4b451f27645fc3b948179d592a82d69a0162cc68316799c3f
3
- size 7895635
 
 
 
 
papers/1-s2.0-S1359836816316882-main.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:fac05273a94954a02f1b7f78a8a2dc48965e6dff8d2417804284df5d5ebf2cc7
3
- size 993983
 
 
 
 
papers/1-s2.0-S2090447920301593-main.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:0811c3ff0f36a2e53819abdd70aab63a47735cf157e081be31a1a0b7fd9a2290
3
- size 2639742
 
 
 
 
papers/2011-EffectofSpecimenSizeonStaticStrengthandDIFofHSCfromSHPBTest.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:bfe41da8fd83964ccc2d63a44cde66663191f0ceec5da19d8ab714571f31e1d0
3
- size 902749
 
 
 
 
papers/Capacitance-based stress self-sensing in cement paste without requiring any admixture.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:91c43a579673112bc4fd4c779e032998854eda1a83cbb52995da1b08cb8a3fbb
3
- size 2607121
 
 
 
 
papers/Capacitive compressive stress self-sensing behavior of cement mortar and its dependence on the thickness.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:10cb37f750e10da02dc2683fac6e0cc21792146f41f043ca421ac485bb78b90e
3
- size 1053149
 
 
 
 
papers/Development of self-sensing ultra-high-performance concrete using hybrid carbon black and carbon nanofibers.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:7038811667d71f1d2dbb5d22c17310ea10b45c1112a4609913bc2003fa69b560
3
- size 18592856
 
 
 
 
papers/Development of sensing concrete Principles, properties and its applications.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:99231674c2f181ba902eddb435422e60fd2aad7b6f0dee8586caf65ffa9e8434
3
- size 4935899
 
 
 
 
papers/EVALUA~1.PDF DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:a17dc91f53a82741e12c8711c992d8193fc891c2aac5a005635d6bb21832323e
3
- size 3449663
 
 
 
 
papers/Effect of silane treatment on microstructure of sisal fibers.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:14e24a7b5089fa8b0fcba20f929ffb0ad8a51d76c7b62dd9a8e793a2dd746bef
3
- size 1767808
 
 
 
 
papers/Graphene family (GFMs), carbon nanotubes (CNTs) and carbon black (CB) on smart materials for civil construction.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:06cf6a6f7ae59ff9f4e8cc253af7022d43096e1d86a9334c87f13198f3300989
3
- size 3325137
 
 
 
 
papers/Influence of the structures of polycarboxylate superplasticizer on its performance in cement-based materials-A review.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:5594e415ae5beb8962fd0f915f2d9326017c8c927ce01ab947525ce2d27d194e
3
- size 2319864
 
 
 
 
papers/Investigating the synergistic effects of carbon fiber and silica fume on concrete strength and eco-efficiency.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:6300a5c9d8e56577739677a3d6fb76bc83794c2e26433e3bee134c6aa96419f5
3
- size 8796244
 
 
 
 
papers/Investigation of 3D Printed Self-Sensing UHPC Composites Using Graphite and Hybrid Carbon Microfibers.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:76a51ea3c14556d9e0816f7bf1a1081c96fecafeaec6318e478256046004c403
3
- size 19966500
 
 
 
 
papers/Ozone treatment of carbon fiber for reinforcing cement.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:1a780e58eeb5fac9eb52da3d8e1b22836eb0efeede7e0c24a34f03f78f3e543a
3
- size 158724
 
 
 
 
papers/PIEZOE~1.PDF DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:b29bdceed88bf961874d5df014ab286e20408a7db568dbf81031d7062cfc0aa3
3
- size 2799712
 
 
 
 
papers/Performance of silica fume slurry treated recycled aggregate concrete reinforced with carbon fibers.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:9b7113d7790e508928c28f5c19646c5ec746d158fd069806f6519b2fa2fb17f9
3
- size 6511841
 
 
 
 
papers/Piezopermittivity for capacitance-based strain stress sensing.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:686a01889e91d7914752144928985ba9c6eb4ea64f4e31272ced5703533f0b3b
3
- size 8547318
 
 
 
 
papers/Review Improving cement-based materials by using silica fume.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:d3b067125bf3d799e0d5cfd92293d7a619bd9c160b99f764866e6780c1168f7d
3
- size 130361
 
 
 
 
papers/Revolutionizing infrastructure The evolving landscape of electricity-based multifunctional concrete from concept to practice.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:b6df06b979a5e5655dc6ce6a7b1d2df44fefa7343e85060871b58835eb380a28
3
- size 51623146
 
 
 
 
papers/S1-An-experimental-study-of-self-sensing-concrete-enhanced_2020_Construction-an.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:b68187d8c4614c3e241bbb4c89e8c14d744533b18f63834a3d26f599a569fcb5
3
- size 10170858
 
 
 
 
papers/S10-Enhancing-self-stress-sensing-ability-of-smart-ultra-high_2021_Journal-of-Bu.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:bab3678971e41461f6f0d19678d0c93b31b9d6c8523d45b2cdfaea9dc84b5751
3
- size 12180099
 
 
 
 
papers/S100-C~1.PDF DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:c4c288018725ff22661b823c066bad8fb7d0f871cfc74c39cabee284b22a684e
3
- size 16436378
 
 
 
 
papers/S11-Environment-Friendly, Self-Sensing Concrete Blended with Byproduct Wastes.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:0de399fce2dfc1ea5b910ccaf28c466847908bf0f19fde5818dba1d383dba17e
3
- size 4414928
 
 
 
 
papers/S12-Hybrid-effects-of-steel-fiber-and-carbon-nanotube-on-s_2018_Construction-and.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:0219166e4a61d8e1bb036e7a3d0eb64d09f0f2eebbed1c051c123b2ae0d1c9be
3
- size 6352700
 
 
 
 
papers/S13-Increasing-self-sensing-capability-of-carbon-nanotubes-c_2020_Construction-a.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:2b6961eb33c2dc1945e80cb424ca0e60be831739795c3d3ed861debd4bc47c00
3
- size 2491685
 
 
 
 
papers/S14-Influence-of-carbon-nanofiber-content-and-sodium-chloride-_2019_Case-Studies.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:e8a467d09713940de2b53cf79a2558aedcb8f88e99396304bd18324ea75e9fbf
3
- size 1429796
 
 
 
 
papers/S15-Influence-of-water-ingress-on-the-electrical-properties-_2021_Journal-of-Bui.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:dc378192f5970beb777212a40e11edc194c88d0d014b6a4c23388dd350a7c05e
3
- size 8114891
 
 
 
 
papers/S16-Investigations-on-scalable-fabrication-procedures-for-sel_2016_Cement-and-Co.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:c019a8649804527c6f6946f0630958baafa168c30c3a7fad8ac1714f5d83af00
3
- size 3699381
 
 
 
 
papers/S17-Cross tension and compression loading and large-scale testing of strain and damage sensing smart concrete.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:8a3f2ace2a355e9ad3fe8f7a8509752295d16f5254b5ddb26e1e063b0fadfce3
3
- size 12549353
 
 
 
 
papers/S18-Nano graphite platelets-enabled piezoresistive cementitious composites for structural health monitoring.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:1b6351f0d89ef05de0842a767ca3d185144071d09703518c511a55a32730f6b7
3
- size 6955295
 
 
 
 
papers/S19-Self-sensing-piezoresistive-cement-composite-loaded_2017_Cement-and-Concrete.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:0b89c68444198a3125bc36d7d7ad895c85679378ddd950574e941f4482cc56b0
3
- size 1291076
 
 
 
 
papers/S2-Characterization-of-smart-brass-fiber-reinforced-co_2020_Construction-and-Bu.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:c573ef904178659e66b169c74a6cbd7805e09145deceeb5cd447863817f42895
3
- size 3456970
 
 
 
 
papers/S20-IN~1.PDF DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:ef0dbea7d457fa02864341d1690484c47dbd39ab0a1b7a85062ce1640e907371
3
- size 1178272
 
 
 
 
papers/S21-Mechanical, electrical and self-sensing properties of cementitious mortars containing short carbon fibers.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:684a75200bebe7438346021f784154f769d6b61275f0268fd970f42c5ad467e2
3
- size 916061
 
 
 
 
papers/S22-Improved strain sensing properties of cement-based sensors through enhanced carbon nanotube dispersion.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:e596ce613b5af3083c9738328c5aeb85d6c950751ace1fdfedd695044b25db26
3
- size 7881761
 
 
 
 
papers/S23-Increasing self-sensing capability of carbon nanotubes cement-based materials by simultaneous addition of Ni nanofibers.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:b11d51d6ed34e67eb268940b8389bf678e2387474c4e38b23c66214789132d37
3
- size 2491685
 
 
 
 
papers/S24-Multifunctional-self-sensing-and-ductile-cementit_2019_Cement-and-Concrete-R.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:e3f581bb63eff732f22b0019ea8cdb495dae35b6c6b7aae88a9b127efb34abcb
3
- size 16496962
 
 
 
 
papers/S25-Self-sensing-capability-of-ultra-high-performance-concr_2018_Sensors-and-Act.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:681f62bb383c1466a88694f215a0b0575c1094ffe8be40fe865105b987e38d0f
3
- size 5220733
 
 
 
 
papers/S26-TE~1.PDF DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:456f19cca981522e080236b4552cc96970f0cdd2342938d99e06cc1b00ab8e61
3
- size 2185689
 
 
 
 
papers/S27-Effect of aspect ratio on strain sensing capacity of carbon fiber reinforced cement composites.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:fe60fd559cc6f743e238a520b680d0d02bb555933328a5a6c0cf01ea9fd0aaa4
3
- size 2781671
 
 
 
 
papers/S28-Smart Graphite–Cement Composites with Low Percolation Threshold.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:5f8238daf3fc5e20e13de68491a4c58d64253d40ced2d96b7cbe491c05cddfe2
3
- size 5383561
 
 
 
 
papers/S29-Hybrid Carbon Microfibers-Graphite Fillers for Piezoresistive Cementitious Composites.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:9b35eaed680f105a0d35fd4b5f704552d9b9dddfbf491871bbbb70fd237da632
3
- size 15621213
 
 
 
 
papers/S3-Effect of characteristics of assembly unit of CNTNCB composite fillers on properties of smart cement-based materials.pdf DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:7bc5d4db3e5f2048a09afcab1e919041bef9ba87abbfac7dd287e14bae6648ac
3
- size 2216621