Spaces:
Running
Running
user
commited on
Commit
·
219d24c
1
Parent(s):
b5553ae
update. remote api focus
Browse files- app.py +83 -15
- character_generator.py +0 -10
- model_loader.py +0 -15
- pdf_processor.py +0 -27
- project_ouline.md +10 -1
- requirements.txt +2 -1
app.py
CHANGED
@@ -2,6 +2,11 @@ from flask import Flask, request, jsonify, send_from_directory
|
|
2 |
import requests
|
3 |
import os
|
4 |
from dotenv import load_dotenv
|
|
|
|
|
|
|
|
|
|
|
5 |
|
6 |
load_dotenv()
|
7 |
|
@@ -9,18 +14,81 @@ app = Flask(__name__)
|
|
9 |
|
10 |
API_URL = "https://api-inference.huggingface.co/models/"
|
11 |
headers = {"Authorization": f"Bearer {os.getenv('HUGGINGFACE_API_KEY')}"}
|
12 |
-
|
13 |
-
# Sample text for testing
|
14 |
-
sample_text = """
|
15 |
-
This is a sample text for testing our RAG chatbot.
|
16 |
-
It contains information about artificial intelligence and machine learning.
|
17 |
-
AI and ML are revolutionizing various industries and improving efficiency.
|
18 |
-
"""
|
19 |
|
20 |
def query(payload, model):
|
21 |
response = requests.post(API_URL + model, headers=headers, json=payload)
|
22 |
return response.json()
|
23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
@app.route('/')
|
25 |
def home():
|
26 |
return send_from_directory('.', 'index.html')
|
@@ -29,17 +97,17 @@ def home():
|
|
29 |
def ask():
|
30 |
prompt = request.json['question']
|
31 |
|
32 |
-
#
|
33 |
-
embedding_model = "sentence-transformers/all-MiniLM-L6-v2"
|
34 |
-
context_embedding = query({"inputs": sample_text}, embedding_model)[0]
|
35 |
query_embedding = query({"inputs": prompt}, embedding_model)[0]
|
36 |
|
37 |
-
#
|
38 |
-
similarity = sum(a*b for a, b in zip(
|
|
|
|
|
|
|
|
|
39 |
|
40 |
-
|
41 |
-
generator_model = "google/flan-t5-small"
|
42 |
-
input_text = f"Context: {sample_text}\n\nQuestion: {prompt}\n\nAnswer:"
|
43 |
response = query({"inputs": input_text}, generator_model)[0]["generated_text"]
|
44 |
|
45 |
return jsonify({'response': response})
|
|
|
2 |
import requests
|
3 |
import os
|
4 |
from dotenv import load_dotenv
|
5 |
+
import traceback
|
6 |
+
from PIL import Image
|
7 |
+
from pdf2image import convert_from_bytes
|
8 |
+
import base64
|
9 |
+
from io import BytesIO
|
10 |
|
11 |
load_dotenv()
|
12 |
|
|
|
14 |
|
15 |
API_URL = "https://api-inference.huggingface.co/models/"
|
16 |
headers = {"Authorization": f"Bearer {os.getenv('HUGGINGFACE_API_KEY')}"}
|
17 |
+
HF_REPO_ID = os.getenv('HF_REPO_ID') # Your Hugging Face repo ID
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
def query(payload, model):
|
20 |
response = requests.post(API_URL + model, headers=headers, json=payload)
|
21 |
return response.json()
|
22 |
|
23 |
+
# Process PDFs using Hugging Face's PDF processing model
|
24 |
+
def process_pdfs():
|
25 |
+
pdf_url = f"https://huggingface.co/spaces/{HF_REPO_ID}/resolve/main/data/your_pdf_file.pdf"
|
26 |
+
|
27 |
+
try:
|
28 |
+
# Download PDF
|
29 |
+
pdf_response = requests.get(pdf_url)
|
30 |
+
pdf_response.raise_for_status() # This will raise an exception for HTTP errors
|
31 |
+
|
32 |
+
print(f"PDF downloaded successfully. Content length: {len(pdf_response.content)} bytes")
|
33 |
+
|
34 |
+
# Convert PDF to images
|
35 |
+
images = convert_from_bytes(pdf_response.content)
|
36 |
+
print(f"Converted PDF to {len(images)} images")
|
37 |
+
|
38 |
+
# Process each image
|
39 |
+
vision_model = "google/vit-base-patch16-224"
|
40 |
+
summaries = []
|
41 |
+
|
42 |
+
for i, image in enumerate(images):
|
43 |
+
# Convert image to base64
|
44 |
+
buffered = BytesIO()
|
45 |
+
image.save(buffered, format="PNG")
|
46 |
+
img_str = base64.b64encode(buffered.getvalue()).decode()
|
47 |
+
|
48 |
+
# Process image with vision model
|
49 |
+
payload = {
|
50 |
+
"inputs": [
|
51 |
+
{
|
52 |
+
"image": img_str,
|
53 |
+
"text": "Describe the content of this image in detail."
|
54 |
+
}
|
55 |
+
]
|
56 |
+
}
|
57 |
+
response = query(payload, vision_model)
|
58 |
+
print(f"Page {i+1} processing response:", json.dumps(response, indent=2))
|
59 |
+
|
60 |
+
if isinstance(response, list) and len(response) > 0 and 'generated_text' in response[0]:
|
61 |
+
summaries.append(response[0]['generated_text'])
|
62 |
+
else:
|
63 |
+
summaries.append(f"Error processing page {i+1}")
|
64 |
+
|
65 |
+
return " ".join(summaries)
|
66 |
+
except Exception as e:
|
67 |
+
print(f"Error in process_pdfs: {str(e)}")
|
68 |
+
print(traceback.format_exc())
|
69 |
+
return f"Error processing PDF: {str(e)}"
|
70 |
+
|
71 |
+
# Get the summary of PDFs
|
72 |
+
pdf_summary = process_pdfs()
|
73 |
+
print("PDF Summary:", pdf_summary)
|
74 |
+
|
75 |
+
# Get embeddings for the summary
|
76 |
+
embedding_model = "sentence-transformers/all-MiniLM-L6-v2"
|
77 |
+
if not pdf_summary.startswith("Error"):
|
78 |
+
try:
|
79 |
+
summary_embedding = query({"inputs": pdf_summary}, embedding_model)[0]
|
80 |
+
print("Successfully created summary embedding")
|
81 |
+
except Exception as e:
|
82 |
+
print(f"Error getting embedding: {str(e)}")
|
83 |
+
print(traceback.format_exc())
|
84 |
+
summary_embedding = None
|
85 |
+
else:
|
86 |
+
print("Skipping embedding due to PDF processing error")
|
87 |
+
summary_embedding = None
|
88 |
+
|
89 |
+
if summary_embedding is None:
|
90 |
+
print("WARNING: summary_embedding is None. The chatbot will not be able to provide meaningful responses.")
|
91 |
+
|
92 |
@app.route('/')
|
93 |
def home():
|
94 |
return send_from_directory('.', 'index.html')
|
|
|
97 |
def ask():
|
98 |
prompt = request.json['question']
|
99 |
|
100 |
+
# Get embedding for the question
|
|
|
|
|
101 |
query_embedding = query({"inputs": prompt}, embedding_model)[0]
|
102 |
|
103 |
+
# Calculate similarity
|
104 |
+
similarity = sum(a*b for a, b in zip(query_embedding, summary_embedding))
|
105 |
+
|
106 |
+
# Generate character response
|
107 |
+
character_traits = "I am a knowledgeable and friendly AI assistant based on the content of the provided PDFs."
|
108 |
+
input_text = f"Character: {character_traits}\nContext: {pdf_summary}\nUser: {prompt}\nCharacter's response:"
|
109 |
|
110 |
+
generator_model = "google/flan-t5-base"
|
|
|
|
|
111 |
response = query({"inputs": input_text}, generator_model)[0]["generated_text"]
|
112 |
|
113 |
return jsonify({'response': response})
|
character_generator.py
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
def generate_character_response(context, prompt):
|
2 |
-
# Define character traits based on your PDF content
|
3 |
-
character_traits = "I am a knowledgeable and friendly AI assistant based on the content of the provided PDF."
|
4 |
-
|
5 |
-
input_text = f"Character: {character_traits}\nContext: {context}\nUser: {prompt}\nCharacter's response:"
|
6 |
-
|
7 |
-
# Use your text generation model here
|
8 |
-
response = generator(input_text, max_length=150, num_return_sequences=1)[0]['generated_text']
|
9 |
-
|
10 |
-
return response
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
model_loader.py
DELETED
@@ -1,15 +0,0 @@
|
|
1 |
-
from transformers import AutoTokenizer, AutoModel, pipeline
|
2 |
-
from huggingface_hub import hf_hub_download
|
3 |
-
|
4 |
-
def load_model():
|
5 |
-
tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
|
6 |
-
model = AutoModel.from_pretrained("sentence-transformers/all-MiniLM-L6-v2", device_map="cpu")
|
7 |
-
return tokenizer, model
|
8 |
-
|
9 |
-
def load_generator():
|
10 |
-
return pipeline('text2text-generation', model='google/flan-t5-base', device_map="cpu")
|
11 |
-
|
12 |
-
def download_pdf():
|
13 |
-
# Replace 'your_pdf_file.pdf' with the actual name of your PDF file on Hugging Face
|
14 |
-
file_path = hf_hub_download(repo_id="your_username/your_repo_name", filename="your_pdf_file.pdf")
|
15 |
-
return file_path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pdf_processor.py
DELETED
@@ -1,27 +0,0 @@
|
|
1 |
-
import fitz # PyMuPDF
|
2 |
-
import numpy as np
|
3 |
-
from transformers import AutoTokenizer, AutoModel
|
4 |
-
import faiss
|
5 |
-
|
6 |
-
def extract_text_from_pdf(file_path):
|
7 |
-
text = ""
|
8 |
-
with fitz.open(file_path) as doc:
|
9 |
-
for page in doc:
|
10 |
-
text += page.get_text()
|
11 |
-
return text
|
12 |
-
|
13 |
-
def process_pdf(pdf_text):
|
14 |
-
chunks = [pdf_text[i:i+512] for i in range(0, len(pdf_text), 512)]
|
15 |
-
tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
|
16 |
-
model = AutoModel.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
|
17 |
-
|
18 |
-
embeddings = []
|
19 |
-
for chunk in chunks:
|
20 |
-
inputs = tokenizer(chunk, padding=True, truncation=True, max_length=512, return_tensors="pt")
|
21 |
-
outputs = model(**inputs)
|
22 |
-
embeddings.append(outputs.last_hidden_state.mean(dim=1).squeeze().numpy())
|
23 |
-
|
24 |
-
embeddings = np.array(embeddings)
|
25 |
-
index = faiss.IndexFlatL2(embeddings.shape[1])
|
26 |
-
index.add(embeddings.astype('float32'))
|
27 |
-
return chunks, index
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
project_ouline.md
CHANGED
@@ -25,4 +25,13 @@ Deploy the project on Hugging Face Spaces
|
|
25 |
Use static HTML for the frontend on Hugging Face Spaces
|
26 |
Use Flask locally to test out features
|
27 |
Focus on PDF functionality for now (VTT and JSON are stretch goals)
|
28 |
-
Store the PDF file in a 'data/' folder within the project structure
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
Use static HTML for the frontend on Hugging Face Spaces
|
26 |
Use Flask locally to test out features
|
27 |
Focus on PDF functionality for now (VTT and JSON are stretch goals)
|
28 |
+
Store the PDF file in a 'data/' folder within the project structure
|
29 |
+
PDF Storage: All PDF files should be stored in the Hugging Face repository, not locally.
|
30 |
+
Model Hosting: All machine learning models (for embedding, text generation, etc.) should be hosted on Hugging Face, not run locally.
|
31 |
+
Heavy Computations: All computationally intensive tasks such as PDF processing, text embedding, and response generation should be performed on Hugging Face's servers.
|
32 |
+
API Usage: Interact with Hugging Face models and services via their API, sending requests from your local machine but having the processing done remotely.
|
33 |
+
Local Testing:
|
34 |
+
Flask Server: Run a local Flask server for development and testing purposes.
|
35 |
+
Minimal Local Dependencies: Keep local dependencies to a minimum, mainly Flask and libraries needed for API interactions.
|
36 |
+
Local Web Interface: Serve a simple HTML/JavaScript frontend locally for testing the chatbot interface.
|
37 |
+
API Key Management: Use environment variables to manage API keys locally without exposing them.
|
requirements.txt
CHANGED
@@ -1,3 +1,4 @@
|
|
1 |
flask
|
2 |
requests
|
3 |
-
python-dotenv
|
|
|
|
1 |
flask
|
2 |
requests
|
3 |
+
python-dotenv
|
4 |
+
PyMuPDF
|