taradutt007 commited on
Commit
1a53fb9
·
verified ·
1 Parent(s): c27480f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +162 -162
app.py CHANGED
@@ -1,162 +1,162 @@
1
- import gradio as gr
2
- import pandas as pd
3
- import re
4
- from langchain.vectorstores import FAISS
5
- from langchain_community.embeddings import HuggingFaceEmbeddings
6
- from huggingface_hub import InferenceClient
7
-
8
- # Paths
9
- CSV_FOLDER = "data"
10
- FAISS_INDEX_PATH = "data/faiss_index_hugface_BAAI_new"
11
-
12
- # Load CSVs
13
- d1 = pd.read_csv(f"{CSV_FOLDER}/dataset1_clean.csv")
14
- d2 = pd.read_csv(f"{CSV_FOLDER}/dataset2_clean.csv")
15
- d3 = pd.read_csv(f"{CSV_FOLDER}/dataset3_clean.csv")
16
- print("✅ CSVs loaded")
17
-
18
- # Load FAISS with dummy embeddings (we won't recompute, just need consistency)
19
- embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-base-en")
20
- faiss_index = FAISS.load_local(FAISS_INDEX_PATH, embeddings, allow_dangerous_deserialization=True)
21
- print("✅ FAISS loaded")
22
-
23
- # Hugging Face Inference API (requires HF_TOKEN in repo secrets)
24
- client = InferenceClient(model="mistralai/Mistral-7B-Instruct-v0.3")
25
-
26
- # Property synonyms
27
- property_synonyms = {
28
- "hardness": ["hv", "hardness", "vicker's hardness", "vickers hardness"],
29
- "bulk modulus": ["d_bulk (gpa)", "bulk modulus", "bulk_modulus"],
30
- "yield_strength": ["ys", "yield stress", "yield strength"],
31
- "ultimate_strength": ["uts", "tensile strength", "ultimate tensile strength"],
32
- "phase": ["phase_label", "bcc/fcc/other", "phase", "microstructure"],
33
- "density": ["density_exp", "density_calc", "density"]
34
- }
35
-
36
- def find_column_for_property(df, property_name):
37
- synonyms = property_synonyms.get(property_name.lower(), [property_name])
38
- for syn in synonyms:
39
- for col in df.columns:
40
- if syn.lower() in col.lower():
41
- return col
42
- return None
43
-
44
- def parse_query_to_filters(question):
45
- query = question.lower()
46
- filters = {}
47
- for phase in ["fcc", "bcc", "hcp", "other"]:
48
- if phase in query:
49
- filters["phase"] = phase
50
- break
51
- numeric_props = ["hardness", "bulk modulus", "yield strength", "ultimate strength", "density"]
52
- for prop in numeric_props:
53
- pattern = rf"{prop}\s*(>=|<=|=|>|<)\s*(\d+\.?\d*)"
54
- match = re.search(pattern, query)
55
- if match:
56
- op, val = match.groups()
57
- filters[prop] = f"{op}{val}"
58
- if f"highest {prop}" in query or f"high {prop}" in query:
59
- filters[prop] = "high"
60
- elif f"lowest {prop}" in query or f"low {prop}" in query:
61
- filters[prop] = "low"
62
- return filters
63
-
64
- def apply_numeric_filter(df, col, filter_value):
65
- if filter_value == "high":
66
- return df.sort_values(by=col, ascending=False)
67
- elif filter_value == "low":
68
- return df.sort_values(by=col, ascending=True)
69
- else:
70
- match = re.match(r"(>=|<=|=|>|<)(\d+\.?\d*)", filter_value)
71
- if not match:
72
- return df
73
- op, val_str = match.groups()
74
- val = float(val_str)
75
- if op == ">": return df[df[col] > val]
76
- if op == "<": return df[df[col] < val]
77
- if op == ">=": return df[df[col] >= val]
78
- if op == "<=": return df[df[col] <= val]
79
- if op == "=": return df[df[col] == val]
80
- return df
81
-
82
- def filter_all_datasets(datasets, queries, top_n=10):
83
- results = {}
84
- for df, name in datasets:
85
- df_filtered = df.copy()
86
- phase_filter = queries.get("phase", None)
87
- if phase_filter:
88
- phase_col = None
89
- for col in df_filtered.columns:
90
- if any(phase_key in col.lower() for phase_key in property_synonyms["phase"]):
91
- phase_col = col
92
- break
93
- if phase_col:
94
- df_filtered = df_filtered[df_filtered[phase_col].str.contains(phase_filter, case=False, na=False)]
95
- else:
96
- continue
97
- for prop, filter_val in queries.items():
98
- if prop == "phase":
99
- continue
100
- col = find_column_for_property(df_filtered, prop)
101
- if col is None:
102
- df_filtered = None
103
- break
104
- df_filtered = df_filtered[df_filtered[col].notna()]
105
- df_filtered = apply_numeric_filter(df_filtered, col, filter_val)
106
- if df_filtered is None or df_filtered.empty:
107
- continue
108
- show_cols = []
109
- if "formula" in df_filtered.columns:
110
- show_cols.append("formula")
111
- for prop in queries.keys():
112
- if prop == "phase":
113
- continue
114
- col = find_column_for_property(df_filtered, prop)
115
- if col and col in df_filtered.columns:
116
- show_cols.append(col)
117
- if phase_filter and phase_col:
118
- show_cols.append(phase_col)
119
- show_cols = [c for c in show_cols if c in df_filtered.columns]
120
- df_filtered = df_filtered[show_cols].head(top_n).copy()
121
- df_filtered["Source"] = name
122
- results[name] = df_filtered
123
- return results
124
-
125
- def query_hea(question, top_k=5):
126
- faiss_results = faiss_index.similarity_search(question, k=top_k)
127
- faiss_text = "\n".join([doc.page_content for doc in faiss_results])
128
- queries = parse_query_to_filters(question)
129
- csv_results_dict = filter_all_datasets(
130
- [(d1, "MPEA"), (d2, "MLPred"), (d3, "Achief")],
131
- queries, top_n=top_k
132
- )
133
- csv_context = ""
134
- for name, df_filtered in csv_results_dict.items():
135
- csv_context += f"\n### {name} matches:\n{df_filtered.to_string(index=False)}\n"
136
- prompt = f"""
137
- You are a materials scientist. Based on the following context, answer precisely.
138
- FAISS context: {faiss_text}
139
- CSV datasets context: {csv_context}
140
- Question: {question}
141
- Answer:
142
- """
143
- output = client.text_generation(prompt, max_new_tokens=512)
144
- merged_df = pd.concat(csv_results_dict.values(), ignore_index=True) if csv_results_dict else pd.DataFrame()
145
- return output, merged_df, faiss_text
146
-
147
- def gradio_query(question):
148
- return query_hea(question)
149
-
150
- demo = gr.Interface(
151
- fn=gradio_query,
152
- inputs=gr.Textbox(lines=2, placeholder="Ask about HEAs..."),
153
- outputs=[
154
- gr.Textbox(label="LLM Answer"),
155
- gr.Dataframe(label="CSV Matches"),
156
- gr.Textbox(label="Paper Context (FAISS)")
157
- ],
158
- title="🔬 HEA Query",
159
- description="Query HEA datasets + FAISS paper embeddings"
160
- )
161
-
162
- demo.launch()
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import re
4
+ from langchain_community.vectorstores import FAISS
5
+ from langchain_community.embeddings import HuggingFaceEmbeddings
6
+ from huggingface_hub import InferenceClient
7
+
8
+ # Paths
9
+ CSV_FOLDER = "data"
10
+ FAISS_INDEX_PATH = "data/faiss_index_hugface_BAAI_new"
11
+
12
+ # Load CSVs
13
+ d1 = pd.read_csv(f"{CSV_FOLDER}/dataset1_clean.csv")
14
+ d2 = pd.read_csv(f"{CSV_FOLDER}/dataset2_clean.csv")
15
+ d3 = pd.read_csv(f"{CSV_FOLDER}/dataset3_clean.csv")
16
+ print("✅ CSVs loaded")
17
+
18
+ # Load FAISS with dummy embeddings (we won't recompute, just need consistency)
19
+ embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-base-en")
20
+ faiss_index = FAISS.load_local(FAISS_INDEX_PATH, embeddings, allow_dangerous_deserialization=True)
21
+ print("✅ FAISS loaded")
22
+
23
+ # Hugging Face Inference API (requires HF_TOKEN in repo secrets)
24
+ client = InferenceClient(model="mistralai/Mistral-7B-Instruct-v0.3")
25
+
26
+ # Property synonyms
27
+ property_synonyms = {
28
+ "hardness": ["hv", "hardness", "vicker's hardness", "vickers hardness"],
29
+ "bulk modulus": ["d_bulk (gpa)", "bulk modulus", "bulk_modulus"],
30
+ "yield_strength": ["ys", "yield stress", "yield strength"],
31
+ "ultimate_strength": ["uts", "tensile strength", "ultimate tensile strength"],
32
+ "phase": ["phase_label", "bcc/fcc/other", "phase", "microstructure"],
33
+ "density": ["density_exp", "density_calc", "density"]
34
+ }
35
+
36
+ def find_column_for_property(df, property_name):
37
+ synonyms = property_synonyms.get(property_name.lower(), [property_name])
38
+ for syn in synonyms:
39
+ for col in df.columns:
40
+ if syn.lower() in col.lower():
41
+ return col
42
+ return None
43
+
44
+ def parse_query_to_filters(question):
45
+ query = question.lower()
46
+ filters = {}
47
+ for phase in ["fcc", "bcc", "hcp", "other"]:
48
+ if phase in query:
49
+ filters["phase"] = phase
50
+ break
51
+ numeric_props = ["hardness", "bulk modulus", "yield strength", "ultimate strength", "density"]
52
+ for prop in numeric_props:
53
+ pattern = rf"{prop}\s*(>=|<=|=|>|<)\s*(\d+\.?\d*)"
54
+ match = re.search(pattern, query)
55
+ if match:
56
+ op, val = match.groups()
57
+ filters[prop] = f"{op}{val}"
58
+ if f"highest {prop}" in query or f"high {prop}" in query:
59
+ filters[prop] = "high"
60
+ elif f"lowest {prop}" in query or f"low {prop}" in query:
61
+ filters[prop] = "low"
62
+ return filters
63
+
64
+ def apply_numeric_filter(df, col, filter_value):
65
+ if filter_value == "high":
66
+ return df.sort_values(by=col, ascending=False)
67
+ elif filter_value == "low":
68
+ return df.sort_values(by=col, ascending=True)
69
+ else:
70
+ match = re.match(r"(>=|<=|=|>|<)(\d+\.?\d*)", filter_value)
71
+ if not match:
72
+ return df
73
+ op, val_str = match.groups()
74
+ val = float(val_str)
75
+ if op == ">": return df[df[col] > val]
76
+ if op == "<": return df[df[col] < val]
77
+ if op == ">=": return df[df[col] >= val]
78
+ if op == "<=": return df[df[col] <= val]
79
+ if op == "=": return df[df[col] == val]
80
+ return df
81
+
82
+ def filter_all_datasets(datasets, queries, top_n=10):
83
+ results = {}
84
+ for df, name in datasets:
85
+ df_filtered = df.copy()
86
+ phase_filter = queries.get("phase", None)
87
+ if phase_filter:
88
+ phase_col = None
89
+ for col in df_filtered.columns:
90
+ if any(phase_key in col.lower() for phase_key in property_synonyms["phase"]):
91
+ phase_col = col
92
+ break
93
+ if phase_col:
94
+ df_filtered = df_filtered[df_filtered[phase_col].str.contains(phase_filter, case=False, na=False)]
95
+ else:
96
+ continue
97
+ for prop, filter_val in queries.items():
98
+ if prop == "phase":
99
+ continue
100
+ col = find_column_for_property(df_filtered, prop)
101
+ if col is None:
102
+ df_filtered = None
103
+ break
104
+ df_filtered = df_filtered[df_filtered[col].notna()]
105
+ df_filtered = apply_numeric_filter(df_filtered, col, filter_val)
106
+ if df_filtered is None or df_filtered.empty:
107
+ continue
108
+ show_cols = []
109
+ if "formula" in df_filtered.columns:
110
+ show_cols.append("formula")
111
+ for prop in queries.keys():
112
+ if prop == "phase":
113
+ continue
114
+ col = find_column_for_property(df_filtered, prop)
115
+ if col and col in df_filtered.columns:
116
+ show_cols.append(col)
117
+ if phase_filter and phase_col:
118
+ show_cols.append(phase_col)
119
+ show_cols = [c for c in show_cols if c in df_filtered.columns]
120
+ df_filtered = df_filtered[show_cols].head(top_n).copy()
121
+ df_filtered["Source"] = name
122
+ results[name] = df_filtered
123
+ return results
124
+
125
+ def query_hea(question, top_k=5):
126
+ faiss_results = faiss_index.similarity_search(question, k=top_k)
127
+ faiss_text = "\n".join([doc.page_content for doc in faiss_results])
128
+ queries = parse_query_to_filters(question)
129
+ csv_results_dict = filter_all_datasets(
130
+ [(d1, "MPEA"), (d2, "MLPred"), (d3, "Achief")],
131
+ queries, top_n=top_k
132
+ )
133
+ csv_context = ""
134
+ for name, df_filtered in csv_results_dict.items():
135
+ csv_context += f"\n### {name} matches:\n{df_filtered.to_string(index=False)}\n"
136
+ prompt = f"""
137
+ You are a materials scientist. Based on the following context, answer precisely.
138
+ FAISS context: {faiss_text}
139
+ CSV datasets context: {csv_context}
140
+ Question: {question}
141
+ Answer:
142
+ """
143
+ output = client.text_generation(prompt, max_new_tokens=512)
144
+ merged_df = pd.concat(csv_results_dict.values(), ignore_index=True) if csv_results_dict else pd.DataFrame()
145
+ return output, merged_df, faiss_text
146
+
147
+ def gradio_query(question):
148
+ return query_hea(question)
149
+
150
+ demo = gr.Interface(
151
+ fn=gradio_query,
152
+ inputs=gr.Textbox(lines=2, placeholder="Ask about HEAs..."),
153
+ outputs=[
154
+ gr.Textbox(label="LLM Answer"),
155
+ gr.Dataframe(label="CSV Matches"),
156
+ gr.Textbox(label="Paper Context (FAISS)")
157
+ ],
158
+ title="🔬 HEA Query",
159
+ description="Query HEA datasets + FAISS paper embeddings"
160
+ )
161
+
162
+ demo.launch()