Spaces:
Sleeping
Sleeping
Delete july3.xlsx
#4
by
OmarOmar91
- opened
This view is limited to 50 files because it contains too many changes.
See the raw diff here.
- .gitattributes +0 -128
- October1.xlsx +0 -0
- app.py +164 -724
- {papers → literature_pdfs}/Carbon fiber reinforced cement improved by using silane-treated carbon fibers.pdf +0 -0
- {papers → literature_pdfs}/Silane-treated carbon fiber for reinforcing cement.pdf +0 -0
- papers/1-s2.0-S095006181732278X-main.pdf +0 -3
- papers/1-s2.0-S0950061820330786-main.pdf +0 -3
- papers/1-s2.0-S1359836816316882-main.pdf +0 -3
- papers/1-s2.0-S2090447920301593-main.pdf +0 -3
- papers/2011-EffectofSpecimenSizeonStaticStrengthandDIFofHSCfromSHPBTest.pdf +0 -3
- papers/Capacitance-based stress self-sensing in cement paste without requiring any admixture.pdf +0 -3
- papers/Capacitive compressive stress self-sensing behavior of cement mortar and its dependence on the thickness.pdf +0 -3
- papers/Development of self-sensing ultra-high-performance concrete using hybrid carbon black and carbon nanofibers.pdf +0 -3
- papers/Development of sensing concrete Principles, properties and its applications.pdf +0 -3
- papers/EVALUA~1.PDF +0 -3
- papers/Effect of silane treatment on microstructure of sisal fibers.pdf +0 -3
- papers/Graphene family (GFMs), carbon nanotubes (CNTs) and carbon black (CB) on smart materials for civil construction.pdf +0 -3
- papers/Influence of the structures of polycarboxylate superplasticizer on its performance in cement-based materials-A review.pdf +0 -3
- papers/Investigating the synergistic effects of carbon fiber and silica fume on concrete strength and eco-efficiency.pdf +0 -3
- papers/Investigation of 3D Printed Self-Sensing UHPC Composites Using Graphite and Hybrid Carbon Microfibers.pdf +0 -3
- papers/Ozone treatment of carbon fiber for reinforcing cement.pdf +0 -3
- papers/PIEZOE~1.PDF +0 -3
- papers/Performance of silica fume slurry treated recycled aggregate concrete reinforced with carbon fibers.pdf +0 -3
- papers/Piezopermittivity for capacitance-based strain stress sensing.pdf +0 -3
- papers/Review Improving cement-based materials by using silica fume.pdf +0 -3
- papers/Revolutionizing infrastructure The evolving landscape of electricity-based multifunctional concrete from concept to practice.pdf +0 -3
- papers/S1-An-experimental-study-of-self-sensing-concrete-enhanced_2020_Construction-an.pdf +0 -3
- papers/S10-Enhancing-self-stress-sensing-ability-of-smart-ultra-high_2021_Journal-of-Bu.pdf +0 -3
- papers/S100-C~1.PDF +0 -3
- papers/S11-Environment-Friendly, Self-Sensing Concrete Blended with Byproduct Wastes.pdf +0 -3
- papers/S12-Hybrid-effects-of-steel-fiber-and-carbon-nanotube-on-s_2018_Construction-and.pdf +0 -3
- papers/S13-Increasing-self-sensing-capability-of-carbon-nanotubes-c_2020_Construction-a.pdf +0 -3
- papers/S14-Influence-of-carbon-nanofiber-content-and-sodium-chloride-_2019_Case-Studies.pdf +0 -3
- papers/S15-Influence-of-water-ingress-on-the-electrical-properties-_2021_Journal-of-Bui.pdf +0 -3
- papers/S16-Investigations-on-scalable-fabrication-procedures-for-sel_2016_Cement-and-Co.pdf +0 -3
- papers/S17-Cross tension and compression loading and large-scale testing of strain and damage sensing smart concrete.pdf +0 -3
- papers/S18-Nano graphite platelets-enabled piezoresistive cementitious composites for structural health monitoring.pdf +0 -3
- papers/S19-Self-sensing-piezoresistive-cement-composite-loaded_2017_Cement-and-Concrete.pdf +0 -3
- papers/S2-Characterization-of-smart-brass-fiber-reinforced-co_2020_Construction-and-Bu.pdf +0 -3
- papers/S20-IN~1.PDF +0 -3
- papers/S21-Mechanical, electrical and self-sensing properties of cementitious mortars containing short carbon fibers.pdf +0 -3
- papers/S22-Improved strain sensing properties of cement-based sensors through enhanced carbon nanotube dispersion.pdf +0 -3
- papers/S23-Increasing self-sensing capability of carbon nanotubes cement-based materials by simultaneous addition of Ni nanofibers.pdf +0 -3
- papers/S24-Multifunctional-self-sensing-and-ductile-cementit_2019_Cement-and-Concrete-R.pdf +0 -3
- papers/S25-Self-sensing-capability-of-ultra-high-performance-concr_2018_Sensors-and-Act.pdf +0 -3
- papers/S26-TE~1.PDF +0 -3
- papers/S27-Effect of aspect ratio on strain sensing capacity of carbon fiber reinforced cement composites.pdf +0 -3
- papers/S28-Smart Graphite–Cement Composites with Low Percolation Threshold.pdf +0 -3
- papers/S29-Hybrid Carbon Microfibers-Graphite Fillers for Piezoresistive Cementitious Composites.pdf +0 -3
- 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 |
-
# -
|
| 4 |
-
# -
|
| 5 |
-
# -
|
| 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
|
| 20 |
from pathlib import Path
|
| 21 |
-
from typing import List, Dict, Any
|
| 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
|
| 43 |
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
| 44 |
-
OPENAI_MODEL
|
|
|
|
| 45 |
try:
|
| 46 |
from openai import OpenAI
|
| 47 |
except Exception:
|
| 48 |
OpenAI = None
|
| 49 |
|
| 50 |
-
|
| 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",
|
| 114 |
-
CURRENT_CHOICES = ["DC", "AC",
|
| 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 |
-
|
| 124 |
-
|
| 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 |
-
|
| 133 |
-
MODEL_STATUS = f"🟢 Loaded model: {Path(p).name}"
|
| 134 |
-
print("[ModelLoad] Loaded:", p)
|
| 135 |
-
return
|
| 136 |
except Exception as e:
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 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 |
-
|
| 169 |
-
|
| 170 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
else:
|
| 172 |
-
|
| 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 |
-
|
| 220 |
-
|
| 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 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
y = float(np.asarray(y).ravel()[0])
|
| 235 |
-
return max(y, 0.0)
|
| 236 |
except Exception as e:
|
| 237 |
-
|
| 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":
|
| 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(
|
| 277 |
elif col == "Current Type":
|
| 278 |
-
cleared.append(
|
| 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 |
-
|
|
|
|
| 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
|
| 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_
|
| 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 |
-
|
| 503 |
page = _extract_page(row["text"])
|
| 504 |
-
|
| 505 |
-
|
| 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 |
-
|
| 517 |
-
|
| 518 |
from sklearn.preprocessing import normalize as sk_normalize
|
| 519 |
-
|
|
|
|
| 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 |
-
|
| 525 |
-
|
| 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 |
-
|
| 538 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 539 |
|
| 540 |
-
|
| 541 |
remain = list(range(len(pool)))
|
| 542 |
-
if not remain:
|
| 543 |
-
return []
|
| 544 |
first = int(np.argmax(rel))
|
| 545 |
-
selected_idx
|
| 546 |
-
selected = [pool[first]]
|
| 547 |
-
remain.remove(first)
|
| 548 |
|
| 549 |
-
|
| 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 |
-
|
| 555 |
-
score = lambda_div *
|
| 556 |
cand_scores.append((score, i))
|
| 557 |
-
if not cand_scores:
|
| 558 |
-
break
|
| 559 |
cand_scores.sort(reverse=True)
|
| 560 |
-
|
| 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 |
-
|
| 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
|
| 579 |
-
|
| 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 |
-
|
| 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
|
| 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 |
-
|
| 617 |
-
|
| 618 |
-
|
| 619 |
-
|
| 620 |
-
|
| 621 |
-
|
| 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 =
|
| 636 |
-
model: str =
|
| 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 |
-
|
| 654 |
-
|
| 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 |
-
|
| 699 |
-
|
| 700 |
-
|
| 701 |
-
|
| 702 |
-
)
|
| 703 |
-
|
| 704 |
-
|
| 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 |
-
|
| 734 |
-
|
| 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 |
-
|
| 742 |
if include_passages:
|
| 743 |
-
|
| 744 |
-
|
| 745 |
-
|
| 746 |
-
|
| 747 |
-
|
| 748 |
-
|
| 749 |
-
|
| 750 |
-
|
| 751 |
-
|
| 752 |
-
|
| 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 (
|
| 820 |
CSS = """
|
| 821 |
-
/*
|
| 822 |
-
* {font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial;}
|
| 823 |
.gradio-container {
|
| 824 |
-
background: linear-gradient(135deg, #
|
| 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="#
|
| 1036 |
body_text_color="#e0f2fe",
|
| 1037 |
-
input_background_fill="#
|
| 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 (
|
| 1075 |
-
"Right: Literature Q&A via Hybrid RAG (BM25 + TF-IDF + optional dense) with MMR sentence selection. "
|
| 1076 |
-
"
|
| 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
|
| 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}
|
| 1090 |
-
f1_dim = gr.Dropdown(DIM_CHOICES, value=
|
| 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=
|
| 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
|
| 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
|
| 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=
|
| 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)",
|
| 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
|
| 1130 |
-
"- Target: Stress GF (MPa
|
| 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)
|
| 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)"
|
| 1156 |
-
pdf_count = len(list(LOCAL_PDF_DIR.glob("**/*.pdf")))
|
| 1157 |
gr.Markdown(
|
| 1158 |
-
|
| 1159 |
-
"
|
| 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"
|
| 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=
|
| 1171 |
-
|
| 1172 |
-
|
| 1173 |
-
|
| 1174 |
-
|
| 1175 |
-
|
| 1176 |
-
|
| 1177 |
-
|
| 1178 |
gr.ChatInterface(
|
| 1179 |
fn=rag_chat_fn,
|
| 1180 |
-
additional_inputs=[
|
| 1181 |
-
|
| 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
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|