GDPR-EDPB-AI / app.py
arsiba's picture
rollback: can't solve performance issues, rollback to lfc
2c2e382
Raw
History Blame Contribute Delete
5.25 kB
import spaces
import pickle
import numpy as np
import faiss
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig, TextIteratorStreamer
from sentence_transformers import SentenceTransformer
import gradio as gr
from threading import Thread
index = faiss.read_index("vector_db/index.faiss")
with open("vector_db/chunks.pkl", "rb") as f:
chunks = pickle.load(f)
with open("vector_db/metadata.pkl", "rb") as f:
metadata_dict = pickle.load(f)
ST = SentenceTransformer("BAAI/bge-large-en-v1.5")
github_base_url = "https://github.com/arsiba/EDPB-AI/blob/main/"
model_id = "HuggingFaceH4/zephyr-7b-beta"
bnb = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16
)
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
tokenizer.pad_token_id = tokenizer.eos_token_id
model = AutoModelForCausalLM.from_pretrained(
model_id,
quantization_config=bnb,
device_map={"": 0},
torch_dtype=torch.bfloat16,
trust_remote_code=True
)
SYS = (
"You are a legal AI assistant specialized in GDPR/EDPB."
"If you cannot find an answer in the context, it's okay to speculate. But if so, make it clear."
"Answer this Question:"
)
@spaces.GPU()
def retrieve(q, k=3):
emb = ST.encode(q)
D, I = index.search(np.array([emb], dtype="float32"), k)
docs, file_sources = [], []
for i in I[0]:
chunk = chunks[i]
meta = metadata_dict[i]
docs.append({"title": meta, "pages": chunk})
file_sources.append(meta)
return docs, file_sources
def make_prompt(q, docs):
context = "\n\n".join(f"Title: {d['title']}\nPages: {d['pages']}" for d in docs)
prompt = f"detailed thinking off\n"
prompt += f"Instruct: {SYS} {q} based on the following documents:\n{context}\nOutput:"
return prompt
def build_markdown_links(file_input):
lines = []
for idx, item in enumerate(file_input, start=1):
url = f"{github_base_url}/{item['directory']}/{item['source']}"
line = f"**Source {idx}:** [{item['source']}]({url}) on page {item['page']}"
lines.append(line)
return "\n\n".join(lines)
def build_markdown_chunks(docs):
lines = []
for idx, d in enumerate(docs, start=1):
title = d['title']['source']
page = d['title']['page']
text = d['pages']
lines.append(f"**Chunk {idx}:** {title} on page {page}\n\n{text}")
return "\n\n".join(lines)
@spaces.GPU()
def qa_fn(faiss_search, question, top_k, temperature, max_tokens):
docs, file_sources = retrieve(faiss_search, top_k)
file_links = build_markdown_links(file_sources)
markdown_chunks = build_markdown_chunks(docs)
prompt = make_prompt(question, docs)[:8000]
inputs = tokenizer(prompt, return_tensors="pt", truncation=True)
inputs = {k: v.to(model.device) for k, v in inputs.items()}
streamer = TextIteratorStreamer(tokenizer, skip_special_tokens=True)
Thread(target=model.generate, kwargs={
**inputs,
"streamer": streamer,
"max_new_tokens": max_tokens,
"do_sample": False,
"temperature": temperature,
"top_p": 0.9,
"eos_token_id": tokenizer.eos_token_id
}).start()
output = ""
for tok in streamer:
output += tok
if "Output:" in output:
output = output.split("Output:", 1)[1].strip()
return "\n# Generated Answer\n", output,"\n# Used Documents\n", file_links, "\n# Used Context\n", markdown_chunks
heading_answer = gr.Markdown(label="Answer Heading")
outputs_answer = gr.Textbox(label="Answer")
heading_links = gr.Markdown(label="Links Heading")
heading_chunks = gr.Markdown(label="Chunks Heading")
outputs_link = gr.Markdown(label="Source Link")
outputs_chunks = gr.Markdown(label="Used Chunks")
demo = gr.Interface(
fn=qa_fn,
inputs=[
gr.Textbox(lines=4, label="What Documents are you looking for?", placeholder="Please change to get propper results:\nDocuments covering the EDPB’s stance on automated decision-making, particularly profiling, under the GDPR. Guidelines on how organizations should inform data subjects about automated decisions and the rights of individuals to object to such decisions."),
gr.Textbox(lines=1, label="What is your question?", placeholder="Please change to get propper results:\nWhat does the EDPB recommend regarding automated decision-making and profiling under the GDPR, and what rights do individuals have in relation to such decisions?"),
],
additional_inputs=[
gr.Slider(1, 10, value=7, step=1, label="Top-K Documents"),
gr.Slider(0.1, 1.0, value=0.6, step=0.05, label="Temperature"),
gr.Slider(64, 1024, value=512, step=64, label="Max Answer Length")
],
additional_inputs_accordion="Advanced Options",
outputs=[
heading_answer,
outputs_answer,
heading_links,
outputs_link,
heading_chunks,
outputs_chunks
],
title="GDPR Legal Assistant",
description="Ask any question about GDPR or EDPB documents.",
allow_flagging="never",
fill_width=True,
)
if __name__ == "__main__":
demo.launch(share=True)