mk1985 commited on
Commit
9dbceb6
·
verified ·
1 Parent(s): 8310805

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +162 -43
app.py CHANGED
@@ -1,51 +1,170 @@
1
- # -----------------------------
2
- # Imports
3
- # -----------------------------
4
- from langchain_openai import ChatOpenAI
5
- from langchain_core.caches import BaseCache # Must be imported before model_rebuild
6
- from langchain.chains import LLMChain
7
- from langchain.prompts import PromptTemplate
8
  import os
9
 
10
- # -----------------------------
11
- # Fix for "class not fully defined" Pydantic error
12
- # -----------------------------
13
- ChatOpenAI.model_rebuild()
14
-
15
- # -----------------------------
16
- # API key setup
17
- # -----------------------------
18
- # For local use: ensure OPENAI_API_KEY is set in your environment
19
- # For Hugging Face Space: add it under Settings → Secrets
20
- if "OPENAI_API_KEY" not in os.environ:
21
- raise ValueError("OPENAI_API_KEY not found. Please set it in environment or Space secrets.")
22
-
23
- # -----------------------------
24
- # Initialise model
25
- # -----------------------------
26
- llm = ChatOpenAI(
27
- model="gpt-4o-mini", # or "gpt-4o", "gpt-4-turbo" etc.
28
- temperature=0,
29
- )
30
 
31
- # -----------------------------
32
- # Example prompt and chain
33
- # -----------------------------
34
- prompt = PromptTemplate(
35
- input_variables=["topic"],
36
- template="Summarise the main challenges and opportunities of using AI in {topic}."
 
 
 
 
 
 
 
 
 
37
  )
38
 
39
- chain = LLMChain(
40
- llm=llm,
41
- prompt=prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  )
43
 
44
- # -----------------------------
45
- # Run the chain
46
- # -----------------------------
47
  if __name__ == "__main__":
48
- topic = "government recordkeeping"
49
- result = chain.run(topic=topic)
50
- print("=== Model Output ===")
51
- print(result)
 
1
+ import gradio as gr
2
+ from langchain_community.vectorstores import Chroma
3
+ from langchain_core.documents import Document
4
+ from langchain_huggingface import HuggingFaceEmbeddings
5
+ import json
 
 
6
  import os
7
 
8
+ # -------------------------------
9
+ # CONFIGURATION
10
+ # -------------------------------
11
+ os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "sk-your-key-here")
12
+
13
+ # -------------------------------
14
+ # LOAD DATA AND BUILD RAG CHAIN
15
+ # -------------------------------
16
+ def clean_metadata(metadata):
17
+ """Convert list values to comma-separated strings for ChromaDB compatibility"""
18
+ cleaned = {}
19
+ for key, value in metadata.items():
20
+ if isinstance(value, list):
21
+ cleaned[key] = ", ".join(str(v) for v in value)
22
+ elif isinstance(value, (str, int, float, bool)) or value is None:
23
+ cleaned[key] = value
24
+ else:
25
+ cleaned[key] = str(value)
26
+ return cleaned
 
27
 
28
+ print("Loading documents...")
29
+ docs = []
30
+ with open("helpwildlife_rag.jsonl", "r", encoding="utf-8") as f:
31
+ for line in f:
32
+ entry = json.loads(line)
33
+ metadata = entry.get("metadata", {})
34
+ docs.append(Document(
35
+ page_content=entry["text"],
36
+ metadata=clean_metadata(metadata)
37
+ ))
38
+ print(f"✓ Loaded {len(docs)} documents")
39
+
40
+ print("Loading embedding model...")
41
+ embeddings = HuggingFaceEmbeddings(
42
+ model_name="sentence-transformers/all-MiniLM-L6-v2"
43
  )
44
 
45
+ print("Building vector store...")
46
+ try:
47
+ vectorstore = Chroma.from_documents(docs, embedding=embeddings)
48
+ except TypeError:
49
+ vectorstore = Chroma.from_documents(docs, embedding_function=embeddings)
50
+
51
+ retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
52
+ print("✓ Vector store created")
53
+
54
+ # Prompt template as string
55
+ prompt_template = """
56
+ You are a compassionate wildlife advice assistant.
57
+ Your only source of information is the text provided in the CONTEXT section below.
58
+ Do not use outside knowledge, guesses, or general reasoning.
59
+ If the context does not contain enough information to answer fully,
60
+ say "I'm not sure based on the available guidance."
61
+
62
+ Never suggest killing or harming any animal.
63
+ Always emphasise that taking an injured or distressed animal to a local wildlife rescue
64
+ or 24/7 animal hospital is the safest and most humane course of action.
65
+ Discourage people from trying to handle or treat the animal themselves,
66
+ and note that general veterinary clinics may euthanise wild animals unnecessarily.
67
+
68
+ Adopt a voice of empathy and respect for all life, consistent with vegan principles:
69
+ there are no animals that are pests, vermin, or unworthy of care.
70
+ Respond clearly and calmly, with brief, practical, step-by-step guidance suitable for the public.
71
+
72
+ ---------------------
73
+ CONTEXT (from HelpWildlife data file):
74
+ {context}
75
+ ---------------------
76
+ QUESTION:
77
+ {question}
78
+
79
+ YOUR ANSWER:
80
+ """
81
+
82
+ # Global LLM variable - will be initialized lazily
83
+ _llm = None
84
+
85
+ def get_llm():
86
+ """Lazy load the LLM only when first needed"""
87
+ global _llm
88
+ if _llm is None:
89
+ from langchain_openai import ChatOpenAI
90
+ from langchain_core.prompts import ChatPromptTemplate
91
+ from langchain_core.output_parsers import StrOutputParser
92
+ from langchain_core.runnables import RunnablePassthrough
93
+
94
+ # Try to fix pydantic issue
95
+ try:
96
+ from langchain_core.caches import BaseCache
97
+ ChatOpenAI.model_rebuild()
98
+ except Exception:
99
+ pass
100
+
101
+ llm = ChatOpenAI(model_name="gpt-4o-mini", temperature=0)
102
+ prompt = ChatPromptTemplate.from_template(prompt_template)
103
+
104
+ def format_docs(docs):
105
+ return "\n\n".join(doc.page_content for doc in docs)
106
+
107
+ _llm = (
108
+ {
109
+ "context": retriever | format_docs,
110
+ "question": RunnablePassthrough()
111
+ }
112
+ | prompt
113
+ | llm
114
+ | StrOutputParser()
115
+ )
116
+ return _llm
117
+
118
+ print("✓ Setup complete - LLM will initialize on first use")
119
+
120
+ # -------------------------------
121
+ # GRADIO INTERFACE
122
+ # -------------------------------
123
+ def ask_wildlife_question(question):
124
+ """Process a wildlife question and return an answer"""
125
+ if not question.strip():
126
+ return "Please enter a question about wildlife."
127
+
128
+ try:
129
+ rag_chain = get_llm()
130
+ answer = rag_chain.invoke(question)
131
+ return answer
132
+ except Exception as e:
133
+ return f"Error: {str(e)}\n\nPlease check your OpenAI API key is set correctly in Space secrets."
134
+
135
+ # Example questions
136
+ examples = [
137
+ "I found a baby hedgehog out during the day. What should I do?",
138
+ "There's a bird that seems injured in my garden. How can I help?",
139
+ "I found a baby bird on the ground. Should I put it back in the nest?",
140
+ "A fox is limping in my backyard. What should I do?",
141
+ "How do I know if a wild animal needs help?"
142
+ ]
143
+
144
+ # Create Gradio interface
145
+ demo = gr.Interface(
146
+ fn=ask_wildlife_question,
147
+ inputs=gr.Textbox(
148
+ label="Ask a Wildlife Question",
149
+ placeholder="e.g., I found a baby bird on the ground...",
150
+ lines=3
151
+ ),
152
+ outputs=gr.Textbox(
153
+ label="Compassionate Advice",
154
+ lines=10
155
+ ),
156
+ title="🦔 Wildlife Rescue Assistant",
157
+ description="""
158
+ Ask questions about helping wildlife in distress. This assistant provides compassionate,
159
+ evidence-based advice prioritizing the wellbeing of all animals.
160
+
161
+ ⚠️ **Important**: This tool provides general guidance only. For urgent situations,
162
+ contact your local wildlife rescue or 24/7 animal hospital immediately.
163
+ """,
164
+ examples=examples,
165
+ theme=gr.themes.Soft(),
166
+ allow_flagging="never"
167
  )
168
 
 
 
 
169
  if __name__ == "__main__":
170
+ demo.launch()