Spaces:
Runtime error
Runtime error
File size: 6,333 Bytes
ea1e6bd |
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 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
import os
import asyncio
from dotenv import load_dotenv
import gradio as gr
from query_utils import process_query_for_rewrite, get_non_autism_response
# helper functions
GEMINI_API_KEY="AIzaSyCUCivstFpC9pq_jMHMYdlPrmh9Bx97dFo"
TAVILY_API_KEY="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"
OPENAI_API_KEY="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"
QDRANT_API_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3MiOiJtIiwiZXhwIjoxNzUxMDUxNzg4fQ.I9J-K7OM0BtcNKgj2d4uVM8QYAHYfFCVAyP4rlZkK2E"
QDRANT_URL="https://6a3aade6-e8ad-4a6c-a579-21f5af90b7e8.us-east4-0.gcp.cloud.qdrant.io"
OPENAI_API_KEY="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"
WEAVIATE_URL="yorcqe2sqswhcaivxvt9a.c0.us-west3.gcp.weaviate.cloud"
WEAVIATE_API_KEY="d2d0VGdZQTBmdTFlOWdDZl9tT2h3WDVWd1NpT1dQWHdGK0xjR1hYeWxicUxHVnFRazRUSjY2VlRUVlkwPV92MjAw"
DEEPINFRA_API_KEY="285LUJulGIprqT6hcPhiXtcrphU04FG4"
DEEPINFRA_BASE_URL="https://api.deepinfra.com/v1/openai"
# if not (DEEPINFRA_TOKEN and WEAVIATE_URL and WEAVIATE_API_KEY):
# raise ValueError("Please set all required keys in .env")
# DeepInfra client
from openai import OpenAI
openai = OpenAI(
api_key=DEEPINFRA_API_KEY,
base_url="https://api.deepinfra.com/v1/openai",
)
# Weaviate client
import weaviate
from weaviate.classes.init import Auth
from contextlib import contextmanager
@contextmanager
def weaviate_client():
client = weaviate.connect_to_weaviate_cloud(
cluster_url=WEAVIATE_URL,
auth_credentials=Auth.api_key(WEAVIATE_API_KEY),
skip_init_checks=True, # <-- This disables gRPC check
)
try:
yield client
finally:
client.close()
# Global path tracker
last_uploaded_path = None
# Embed function
def embed_texts(texts: list[str], batch_size: int = 50) -> list[list[float]]:
all_embeddings = []
for i in range(0, len(texts), batch_size):
batch = texts[i : i + batch_size]
try:
resp = openai.embeddings.create(
model="Qwen/Qwen3-Embedding-8B",
input=batch,
encoding_format="float"
)
batch_embs = [item.embedding for item in resp.data]
all_embeddings.extend(batch_embs)
except Exception as e:
print(f"Embedding error: {e}")
all_embeddings.extend([[] for _ in batch])
return all_embeddings
def encode_query(query: str) -> list[float] | None:
embs = embed_texts([query], batch_size=1)
if embs and embs[0]:
return embs[0]
return None
async def old_Document(query: str, top_k: int = 1) -> dict:
qe = encode_query(query)
if not qe:
return {"answer": []}
try:
with weaviate_client() as client:
coll = client.collections.get("user")
res = coll.query.near_vector(
near_vector=qe,
limit=top_k,
return_properties=["text"]
)
if not getattr(res, "objects", None):
return {"answer": []}
return {
"answer": [obj.properties.get("text", "[No Text]") for obj in res.objects]
}
except Exception as e:
print("RAG Error:", e)
return {"answer": []}
# New functions to support Gradio app
def ingest_file(path: str) -> str:
global last_uploaded_path
last_uploaded_path = path
return f"Old document ingested: {os.path.basename(path)}"
def answer_question(query: str) -> str:
try:
# Process query for rewriting and relevance checking
corrected_query, is_autism_related, rewritten_query = process_query_for_rewrite(query)
# If not autism-related, show direct rejection message
if not is_autism_related:
return get_non_autism_response()
# Use the corrected query for retrieval
rag_resp = asyncio.run(old_Document(corrected_query))
chunks = rag_resp.get("answer", [])
if not chunks:
return "Sorry, I couldn't find relevant content in the old document."
# Combine chunks into a single answer for relevance checking
combined_answer = "\n".join(f"- {c}" for c in chunks)
# NEW: Check if the retrieved content is sufficiently related to autism
from query_utils import check_answer_autism_relevance, get_non_autism_answer_response
answer_relevance_score = check_answer_autism_relevance(combined_answer)
# If answer relevance is below 50%, refuse the answer (updated threshold for enhanced scoring)
if answer_relevance_score < 50:
return get_non_autism_answer_response()
# If sufficiently autism-related, return the answer
return combined_answer
except Exception as e:
return f"Error processing your request: {e}"
# Gradio interface for Old Documents
with gr.Blocks(title="Old Documents RAG") as demo:
gr.Markdown("## Old Documents RAG")
query = gr.Textbox(placeholder="Your question...", lines=2, label="Ask about Old Documents")
doc_file = gr.File(label="Upload Old Document (PDF, DOCX, TXT)")
btn = gr.Button("Submit")
out = gr.Textbox(label="Answer from Old Documents", lines=8, interactive=False)
def process_old_doc(query, doc_file):
if doc_file:
# Save and ingest the uploaded file
upload_dir = os.path.join(os.path.dirname(__file__), "uploaded_docs")
os.makedirs(upload_dir, exist_ok=True)
safe_filename = os.path.basename(doc_file.name)
save_path = os.path.join(upload_dir, safe_filename)
with open(save_path, "wb") as f:
f.write(doc_file.read())
status = ingest_file(save_path)
answer = answer_question(query)
return f"{status}\n\n{answer}"
else:
# Use last uploaded file or return error if none exists
if last_uploaded_path:
answer = answer_question(query)
return f"[Using previously uploaded document: {os.path.basename(last_uploaded_path)}]\n\n{answer}"
else:
return "No document uploaded. Please upload an old document to proceed."
btn.click(fn=process_old_doc, inputs=[query, doc_file], outputs=out)
if __name__ == "__main__":
demo.launch(debug=True) |