decodingdatascience1 commited on
Commit
2541c6e
·
verified ·
1 Parent(s): 6002b59

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -0
app.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #### This for hugging face space for zero gpu
2
+ ##1. create requirements.txt
3
+ ##2.add keys in HF secrets
4
+ ##3. put this in app.py
5
+ # --- Imports ---
6
+ import logging
7
+ import os
8
+ import sys
9
+
10
+ import gradio as gr
11
+ import spaces
12
+
13
+ from pinecone import Pinecone, ServerlessSpec
14
+ from llama_index.core import (
15
+ VectorStoreIndex,
16
+ SimpleDirectoryReader,
17
+ StorageContext,
18
+ Settings,
19
+ PromptTemplate,
20
+ )
21
+ from llama_index.vector_stores.pinecone import PineconeVectorStore
22
+ from llama_index.readers.file import PDFReader
23
+ from llama_index.llms.openai import OpenAI
24
+ from llama_index.embeddings.openai import OpenAIEmbedding
25
+
26
+ # --- Logging ---
27
+ logging.basicConfig(stream=sys.stdout, level=logging.INFO)
28
+ logger = logging.getLogger(__name__)
29
+
30
+ # --- Keys (set these in Space Settings -> Variables and secrets) ---
31
+ OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
32
+ PINECONE_API_KEY = os.getenv("PINECONE_API_KEY")
33
+
34
+
35
+
36
+ # --- LlamaIndex global settings ---
37
+ Settings.llm = OpenAI(model="gpt-4o-mini", temperature=0.2)
38
+ Settings.embed_model = OpenAIEmbedding(model="text-embedding-ada-002")
39
+ Settings.chunk_size = 600
40
+ Settings.chunk_overlap = 200
41
+
42
+ SYSTEM_PROMPT = """You are AYesha, the Decoding Data Science (DDS) Enterprise HR Chatbot. Answer questions exclusively using the attached DDS HR Handbook. Base all responses on the most up-to-date information available in the handbook. Only respond to queries directly related to DDS HR policies as outlined in the handbook.
43
+ Important instructions:
44
+ - Only answer questions directly supported by the latest DDS HR handbook.
45
+ - Decline politely and redirect to the provided email address for any questions outside scope or for confidential information.
46
+ - Always reason before concluding. Only present the answer after checking scope and source.
47
+ Remember: As AYesha, the DDS HR Enterprise Chatbot, you must never provide information outside authorized HR handbook content and always respond respectfully according to these constraints.
48
+ """
49
+
50
+ # LlamaIndex's query engine doesn't accept a `system_prompt=` kwarg — that param only
51
+ # exists on as_chat_engine(). The equivalent for a query engine is a custom QA prompt
52
+ # template, which is what actually enforces AYesha's scope/persona.
53
+ QA_TEMPLATE = PromptTemplate(
54
+ SYSTEM_PROMPT
55
+ + "\n\nContext information is below.\n---------------------\n{context_str}\n---------------------\n"
56
+ "Given the context information and not prior knowledge, answer the query.\n"
57
+ "Query: {query_str}\nAnswer: "
58
+ )
59
+
60
+ # --- Initialize Pinecone ---
61
+ pc = Pinecone(api_key=PINECONE_API_KEY)
62
+ INDEX_NAME = "quickstart"
63
+ DIMENSION = 1536
64
+
65
+ existing_indexes = [idx["name"] for idx in pc.list_indexes()]
66
+
67
+ if INDEX_NAME not in existing_indexes:
68
+ # Only create the index the first time. Deleting + recreating on every
69
+ # restart re-embeds every PDF (real API cost) and risks a race if two
70
+ # cold starts overlap — so we only build the index when it doesn't exist yet.
71
+ pc.create_index(
72
+ name=INDEX_NAME,
73
+ dimension=DIMENSION,
74
+ metric="euclidean",
75
+ spec=ServerlessSpec(cloud="aws", region="us-east-1"),
76
+ )
77
+
78
+ pinecone_index = pc.Index(INDEX_NAME)
79
+ vector_store = PineconeVectorStore(pinecone_index=pinecone_index)
80
+
81
+ # If the index is already populated (from a prior run), just attach to it.
82
+ # Otherwise load the PDFs and build it now.
83
+ stats = pinecone_index.describe_index_stats()
84
+ if stats.get("total_vector_count", 0) > 0:
85
+ index = VectorStoreIndex.from_vector_store(vector_store)
86
+ else:
87
+ documents = SimpleDirectoryReader(
88
+ input_dir="Data", # folder name is case-sensitive — must match exactly what you upload
89
+ required_exts=[".pdf"],
90
+ file_extractor={".pdf": PDFReader()},
91
+ ).load_data()
92
+
93
+ if not documents:
94
+ raise ValueError(
95
+ "No PDF documents were loaded from the 'Data' folder. "
96
+ "Make sure a folder named exactly 'Data' with your PDF(s) is uploaded alongside app.py."
97
+ )
98
+
99
+ storage_context = StorageContext.from_defaults(vector_store=vector_store)
100
+ index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
101
+
102
+ query_engine = index.as_query_engine(text_qa_template=QA_TEMPLATE)
103
+
104
+
105
+ # --- Gradio App ---
106
+ @spaces.GPU
107
+ def query_doc(prompt):
108
+ try:
109
+ response = query_engine.query(prompt)
110
+ return str(response)
111
+ except Exception as e:
112
+ logger.exception("Query failed")
113
+ return f"Error: {str(e)}"
114
+
115
+
116
+ gr.Interface(
117
+ fn=query_doc,
118
+ inputs=gr.Textbox(label="Ask a question about the document"),
119
+ outputs=gr.Textbox(label="Answer"),
120
+ title="DDS Enterprise HR Chatbot — AYesha",
121
+ description="Ask questions related to HR for latest information.",
122
+ ).launch()