MSU576 commited on
Commit
1a1d2ef
Β·
verified Β·
1 Parent(s): 3f79082

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -35
app.py CHANGED
@@ -1720,67 +1720,149 @@ def locator_page():
1720
  # end locator_page()
1721
 
1722
  # GeoMate Ask (RAG) β€” simple chat with memory per site and auto-extract numeric values
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1723
  def rag_page():
1724
  st.header("πŸ€– GeoMate Ask (RAG + Groq)")
1725
  site = st.session_state["sites"][st.session_state["active_site"]]
1726
- st.markdown("Chat with GeoMate. The LLM has memory per site for this session; any engineering values provided will be parsed and saved.")
 
 
 
 
 
 
 
 
1727
  if "rag_history" not in st.session_state:
1728
- st.session_state["rag_history"] = {i: [] for i in range(len(st.session_state["sites"]))}
1729
- hist = st.session_state["rag_history"].get(site["Site ID"], [])
 
 
 
 
1730
  for entry in hist:
1731
  who, text = entry.get("who"), entry.get("text")
1732
  if who == "bot":
1733
  st.markdown(f"<div class='chat-bot'>{text}</div>", unsafe_allow_html=True)
1734
  else:
1735
  st.markdown(f"<div class='chat-user'>{text}</div>", unsafe_allow_html=True)
1736
- user_msg = st.text_input("You:", key="rag_input")
1737
- if st.button("Send", key="rag_send"):
 
 
1738
  if not user_msg.strip():
1739
  st.warning("Enter a message.")
1740
  else:
1741
  # Save user msg
1742
- st.session_state["rag_history"][site["Site ID"]].append({"who":"user","text":user_msg})
1743
- # Build prompt including site context
 
 
 
 
 
 
 
1744
  context = {
1745
- "site": {k:v for k,v in site.items() if k in ["Site Name","lat","lon","USCS","AASHTO","GI","Load Bearing Capacity","Soil Profile","Flood Data","Seismic Data"]},
1746
- "chat_history": st.session_state["rag_history"][site["Site ID"]]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1747
  }
1748
- prompt = f"You are GeoMate AI. Site context: {json.dumps(context)}. User: {user_msg}\nRespond professionally and concisely. If user provides numeric engineering values, return them in the format: [[FIELD: value unit]]."
1749
- resp = groq_generate(prompt, model=st.session_state["llm_model"], max_tokens=400)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1750
  # Save bot reply
1751
- st.session_state["rag_history"][site["Site ID"]].append({"who":"bot","text":resp})
1752
- # Display
 
1753
  st.markdown(f"<div class='chat-bot'>{resp}</div>", unsafe_allow_html=True)
1754
- # Try to extract bracketed fields like [[Load bearing capacity: 2000 psf]]
1755
- import re
1756
- matches = re.findall(r"\[\[([A-Za-z0-9 _/-]+):\s*([0-9.+-eE]+)\s*([A-Za-z%\/]*)\]\]", resp)
 
 
1757
  for m in matches:
1758
- field = m[0].strip()
1759
- val = m[1].strip()
1760
- unit = m[2].strip()
1761
- # Map common fields to site keys
1762
  if "bearing" in field.lower():
1763
  site["Load Bearing Capacity"] = f"{val} {unit}"
1764
  elif "skin" in field.lower():
1765
  site["Skin Shear Strength"] = f"{val} {unit}"
1766
  elif "compaction" in field.lower():
1767
  site["Relative Compaction"] = f"{val} {unit}"
1768
- st.success("Response saved and any recognized numeric fields auto-stored in the site data.")
1769
-
1770
- # Reports page β€” conversational missing-parameter bot & PDF generation
1771
- REPORT_FIELDS = [
1772
- ("Load Bearing Capacity","kPa or psf"),
1773
- ("Skin Shear Strength","kPa"),
1774
- ("Relative Compaction","%"),
1775
- ("Rate of Consolidation","mm/yr or days"),
1776
- ("Nature of Construction","text"),
1777
- ("Borehole Count","number"),
1778
- ("Max Depth (m)","m"),
1779
- ("SPT N (avg)","blows/ft"),
1780
- ("CBR (%)","%"),
1781
- ("Allowable Bearing (kPa)","kPa")
1782
- ]
1783
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1784
 
1785
  def reports_page():
1786
  st.header("πŸ“‘ Reports β€” Classification & Full Geotechnical")
 
1720
  # end locator_page()
1721
 
1722
  # GeoMate Ask (RAG) β€” simple chat with memory per site and auto-extract numeric values
1723
+ import re, json, pickle
1724
+ import streamlit as st
1725
+ from langchain.vectorstores import FAISS
1726
+ from langchain.embeddings import HuggingFaceEmbeddings
1727
+
1728
+ # -------------------
1729
+ # Load FAISS DB once
1730
+ # -------------------
1731
+ @st.cache_resource
1732
+ def load_faiss():
1733
+ # Adjust path to where you unzip faiss_books_db.zip
1734
+ faiss_dir = "faiss_books_db"
1735
+ # embeddings must match the one you used when creating index
1736
+ embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
1737
+
1738
+ with open(f"{faiss_dir}/index.pkl", "rb") as f:
1739
+ data = pickle.load(f)
1740
+ vectorstore = FAISS.load_local(faiss_dir, embeddings, allow_dangerous_deserialization=True)
1741
+ return vectorstore
1742
+
1743
+ vectorstore = load_faiss()
1744
+
1745
+
1746
+ # -------------------
1747
+ # RAG Chat Page
1748
+ # -------------------
1749
  def rag_page():
1750
  st.header("πŸ€– GeoMate Ask (RAG + Groq)")
1751
  site = st.session_state["sites"][st.session_state["active_site"]]
1752
+
1753
+ # --- Ensure Site ID exists ---
1754
+ if site.get("Site ID") is None:
1755
+ site_id = st.session_state["sites"].index(site)
1756
+ site["Site ID"] = site_id
1757
+ else:
1758
+ site_id = site["Site ID"]
1759
+
1760
+ # --- Initialize rag_history properly ---
1761
  if "rag_history" not in st.session_state:
1762
+ st.session_state["rag_history"] = {}
1763
+ if site_id not in st.session_state["rag_history"]:
1764
+ st.session_state["rag_history"][site_id] = []
1765
+
1766
+ # --- Display chat history ---
1767
+ hist = st.session_state["rag_history"][site_id]
1768
  for entry in hist:
1769
  who, text = entry.get("who"), entry.get("text")
1770
  if who == "bot":
1771
  st.markdown(f"<div class='chat-bot'>{text}</div>", unsafe_allow_html=True)
1772
  else:
1773
  st.markdown(f"<div class='chat-user'>{text}</div>", unsafe_allow_html=True)
1774
+
1775
+ # --- User input ---
1776
+ user_msg = st.text_input("You:", key=f"rag_input_{site_id}")
1777
+ if st.button("Send", key=f"rag_send_{site_id}"):
1778
  if not user_msg.strip():
1779
  st.warning("Enter a message.")
1780
  else:
1781
  # Save user msg
1782
+ st.session_state["rag_history"][site_id].append(
1783
+ {"who": "user", "text": user_msg}
1784
+ )
1785
+
1786
+ # --- Retrieve from FAISS ---
1787
+ docs = vectorstore.similarity_search(user_msg, k=3)
1788
+ context_text = "\n".join([d.page_content for d in docs])
1789
+
1790
+ # --- Build context for LLM ---
1791
  context = {
1792
+ "site": {
1793
+ k: v
1794
+ for k, v in site.items()
1795
+ if k in [
1796
+ "Site Name",
1797
+ "lat",
1798
+ "lon",
1799
+ "USCS",
1800
+ "AASHTO",
1801
+ "GI",
1802
+ "Load Bearing Capacity",
1803
+ "Soil Profile",
1804
+ "Flood Data",
1805
+ "Seismic Data",
1806
+ ]
1807
+ },
1808
+ "chat_history": st.session_state["rag_history"][site_id],
1809
  }
1810
+
1811
+ prompt = (
1812
+ f"You are GeoMate AI, an expert geotechnical assistant.\n\n"
1813
+ f"Relevant references:\n{context_text}\n\n"
1814
+ f"Site context: {json.dumps(context)}\n\n"
1815
+ f"User: {user_msg}\n\n"
1816
+ f"Answer concisely, include citations [ref:source]. "
1817
+ f"If user provides numeric engineering values, return them in the format: [[FIELD: value unit]]."
1818
+ )
1819
+
1820
+ # Call your Groq model (replace placeholder with real call)
1821
+ # resp = groq_generate(prompt, model=st.session_state["llm_model"], max_tokens=500)
1822
+ resp = (
1823
+ "This is a placeholder RAG response using FAISS context. "
1824
+ "[ref:Soil_Handbook_2021] [[Load Bearing Capacity: 220 kPa]]"
1825
+ )
1826
+
1827
  # Save bot reply
1828
+ st.session_state["rag_history"][site_id].append({"who": "bot", "text": resp})
1829
+
1830
+ # Display reply
1831
  st.markdown(f"<div class='chat-bot'>{resp}</div>", unsafe_allow_html=True)
1832
+
1833
+ # Extract bracketed numeric values
1834
+ matches = re.findall(
1835
+ r"\[\[([A-Za-z0-9 _/-]+):\s*([0-9.+-eE]+)\s*([A-Za-z%\/]*)\]\]", resp
1836
+ )
1837
  for m in matches:
1838
+ field, val, unit = m[0].strip(), m[1].strip(), m[2].strip()
 
 
 
1839
  if "bearing" in field.lower():
1840
  site["Load Bearing Capacity"] = f"{val} {unit}"
1841
  elif "skin" in field.lower():
1842
  site["Skin Shear Strength"] = f"{val} {unit}"
1843
  elif "compaction" in field.lower():
1844
  site["Relative Compaction"] = f"{val} {unit}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1845
 
1846
+ st.success(
1847
+ "Response saved βœ… with citations and recognized numeric fields auto-stored in site data."
1848
+ )
1849
+
1850
+
1851
+ # -------------------
1852
+ # Report fields (still needed in reports_page)
1853
+ # -------------------
1854
+ REPORT_FIELDS = [
1855
+ ("Load Bearing Capacity", "kPa or psf"),
1856
+ ("Skin Shear Strength", "kPa"),
1857
+ ("Relative Compaction", "%"),
1858
+ ("Rate of Consolidation", "mm/yr or days"),
1859
+ ("Nature of Construction", "text"),
1860
+ ("Borehole Count", "number"),
1861
+ ("Max Depth (m)", "m"),
1862
+ ("SPT N (avg)", "blows/ft"),
1863
+ ("CBR (%)", "%"),
1864
+ ("Allowable Bearing (kPa)", "kPa"),
1865
+ ]
1866
 
1867
  def reports_page():
1868
  st.header("πŸ“‘ Reports β€” Classification & Full Geotechnical")