jeremierostan's picture
Update app.py
b1a2bc2 verified
raw
history blame
4.58 kB
import os
import json
import gradio as gr
from typing import List, Dict
from langchain.document_loaders import AirtableLoader
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI
from langchain.schema import SystemMessage, HumanMessage
from langchain.text_splitter import CharacterTextSplitter
from langchain.docstore.document import Document
# Set up API keys
AIRTABLE_API_KEY = os.getenv("AIRTABLE_API_KEY")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
base_id = os.getenv("base_id")
table_id = os.getenv("table_id")
view = os.getenv("view")
def load_airtable_data() -> List[Dict]:
"""Load data from Airtable and return as a list of dictionaries."""
loader = AirtableLoader(os.environ["AIRTABLE_API_KEY"], table_id, base_id, view=view)
documents = loader.load()
data = []
for doc in documents:
try:
# Try to parse the JSON content
record = json.loads(doc.page_content)
data.append(record)
except json.JSONDecodeError:
# If JSON parsing fails, use the raw content
print(f"Warning: Could not parse JSON for document: {doc.page_content[:100]}...")
data.append({"raw_content": doc.page_content})
return data
# Load Airtable data
try:
airtable_data = load_airtable_data()
print(f"Successfully loaded {len(airtable_data)} records from Airtable.")
except Exception as e:
print(f"Error loading Airtable data: {str(e)}")
airtable_data = []
# Prepare documents for embedding
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
documents = [Document(page_content=json.dumps(record)) for record in airtable_data]
split_documents = text_splitter.split_documents(documents)
# Initialize the embedding model and FAISS index
embedding_model = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(split_documents, embedding_model)
# Define the retrieval model
retriever = vectorstore.as_retriever()
# Define the chat model
chat_model = ChatOpenAI(model="gpt-4o")
# Define a custom prompt for context
system_message_content = """
#Context
You are a school assistant with strong database Q&A capabilities.
Your role is to help educators keep track of students' assignments in different classes.
This is a complex problem, because each student has their own menu of classes (they choose their classes), so that it can be hard for a teacher to know what assignments their students might have
in other classes. Solving this requires carefully analyzing a database.
You have acces to a database with the following format:
-List of classes
-List of DUE dates, when students turn in work done at home
-List of DO dates, when students take assessments in class
-List of DUE assignments
-List of DO assessments
The policy is that students cannot have to DO more than 2 in-class assignments on a given day.
HOWEVER, they might have 2 or more assignments DUE on the same day.
#Instructions
When asked a question about a class and a date:
-look up all students enrolled in this class
-look up what other classes they are enrolled in
-look up if those other classes have "DO" assessments on that day
-Deduce whether any student in the class already has 2 or more "DO" assessments on that day
Keep this procedure in mind when answering other questions as well.
Be concise and factual in your answers unless asked for more details.
Base all of your answers on the data provided.
Double-check your answers, and if you don't know the answer, say that you don't know.
"""
# Create the QA chain
qa_chain = RetrievalQA.from_chain_type(
llm=chat_model,
chain_type="stuff",
retriever=retriever,
return_source_documents=True
)
def ask_question(question: str) -> str:
"""Ask a question about the Airtable data."""
# Combine the system message and user question
full_query = f"{system_message_content}\n\nHuman: {question}\n\nAssistant:"
# Get the response from the QA chain
response = qa_chain({"query": full_query})
# Return the response content
return response['result']
# Define the Gradio interface
def gradio_interface(question: str) -> str:
return ask_question(question)
# Set up Gradio interface
iface = gr.Interface(
fn=gradio_interface,
inputs="text",
outputs="text",
title="Summative Assessment Tracker",
description="I am here to help you schedule summative assessments for your students"
)
# Launch the Gradio app
iface.launch(debug=True)