Spaces:
Running
Running
File size: 5,282 Bytes
77253fa |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
import os, io, re
import pandas as pd
from sklearn.metrics import accuracy_score
from bert_score import score as bert_score
import google.generativeai as genai
from modtran_gemini import (
handle_user_query,
initialize_chatbot_agent,
get_uploaded_text,
get_text_chunks,
get_vectorstore,
set_global_vectorstore,
self_reasoning,
faiss_search_with_keywords,
faiss_search_with_reasoning
)
from langchain_openai import ChatOpenAI
class GeminiLLM:
def __init__(self, model_name="models/gemini-1.5-pro-latest", api_key=None):
api_key = api_key or os.getenv("GOOGLE_API_KEY")
if not api_key:
raise ValueError("Missing GOOGLE_API_KEY")
genai.configure(api_key=api_key)
self.model = genai.GenerativeModel(model_name)
def predict(self, prompt: str) -> str:
response = self.model.generate_content(prompt)
return response.text.strip()
# Load CSV dataset (ensure columns are 'question', 'answer' with no extra spaces)
df = pd.read_csv("modtran_dataset.csv")
df.columns = df.columns.str.strip() # Strip whitespace from column names
# Load the MODTRAN user manual
with open("MODTRAN 6 User's Manual.pdf", "rb") as f:
file_obj = io.BytesIO(f.read())
file_obj.name = "MODTRAN 6 User's Manual.pdf"
uploaded_files = [file_obj]
# Document processing
raw_text = get_uploaded_text(uploaded_files)
text_chunks = get_text_chunks(raw_text)
vectorstore = get_vectorstore(text_chunks)
set_global_vectorstore(vectorstore)
llm = GeminiLLM()
# Direct retrieval + answer generation
def direct_llm_rag_response(question):
from modtran_gemini import vectorstore_global
if vectorstore_global is None:
raise ValueError("Vectorstore is not initialized.")
# Retrieve relevant documents
retriever = vectorstore_global.as_retriever(search_kwargs={"k": 20})
docs = retriever.get_relevant_documents(question)
# Build a simple prompt with raw context
context = "\n\n".join([doc.page_content for doc in docs])
prompt = f"""
You are an AI assistant that analyzes the context provided to answer the user's query comprehensively and clearly.
Answer in a concise, factual way using the terminology from the context. Avoid extra explanation unless explicitly asked.
If asked for the page number,YOU MUST mention the page number.
### Example 1:
**Question:** What is the purpose of the MODTRAN GUI?
**Context:**
[Page 10 of the docuemnt] The MODTRAN GUI helps users set parameters and visualize the model's output.
**Answer:** The MODTRAN GUI assists users in parameter setup and output visualization. You can find the answer at Page 10 of the document provided.
### Example 2:
**Question:** How do you run MODTRAN on Linux? Answer with page number.
**Context:**
[Page 15 of the docuemnt] On Linux systems, MODTRAN can be run using the `mod6c` binary via terminal.
**Answer:** Use the `mod6c` binary via terminal. (Page 15)
### Now answer:
**Question:** {question}
**Context:**
{context}
**Answer:**
"""
return llm.predict(prompt)
# Predict answers
df["predicted"] = df["question"].apply(direct_llm_rag_response)
# Clean up answers
true_answers = df["answer"].str.lower().str.strip()
pred_answers = df["predicted"].str.lower().str.strip()
# Normalize answers
def normalize_text(s):
s = s.lower()
s = re.sub(r'\b(a|an|the)\b', ' ', s)
s = re.sub(r'[^a-z0-9]', ' ', s)
return ' '.join(s.split())
normalized_preds = [normalize_text(p) for p in pred_answers]
normalized_refs = [normalize_text(r) for r in true_answers]
# Token-level F1
def compute_f1(pred, ref):
pred_tokens = pred.split()
ref_tokens = ref.split()
common = set(pred_tokens) & set(ref_tokens)
if not common:
return 0.0
precision = len(common) / len(pred_tokens)
recall = len(common) / len(ref_tokens)
return 2 * precision * recall / (precision + recall)
def manual_tool_routing(question):
if "how" in question.lower():
context = faiss_search_with_reasoning(question)
else:
context = faiss_search_with_keywords(question)
return self_reasoning(question, context)
# Create predictions using different strategies
df["agent_predicted"] = df["question"].apply(manual_tool_routing)
df["keyword_predicted"] = df["question"].apply(faiss_search_with_keywords)
df["reasoning_predicted"] = df["question"].apply(faiss_search_with_reasoning)
refs = df["answer"].str.lower().str.strip()
for col in ["agent_predicted", "keyword_predicted", "reasoning_predicted"]:
preds = df[col].str.lower().str.strip()
normalized_preds = [normalize_text(p) for p in preds]
normalized_refs = [normalize_text(r) for r in refs]
em = sum([int(p == r) for p, r in zip(normalized_preds, normalized_refs)]) / len(refs)
f1 = sum([compute_f1(p, r) for p, r in zip(normalized_preds, normalized_refs)]) / len(refs)
P, R, F1_bert = bert_score(preds.tolist(), refs.tolist(), lang="en", verbose=True)
bert_f1 = F1_bert.mean().item()
print(f"\n🔹 Evaluation for: {col}")
print(f" - Exact Match: {em:.3f}")
print(f" - F1 Score: {f1:.3f}")
print(f" - BERTScore F1: {bert_f1:.3f}")
df[f"{col}_bert_f1"] = F1_bert.numpy() |