test / _backend /utils /ai.py
aiioe's picture
Automated build & deploy
e454383 verified
Raw History Blame Contribute Delete
4.48 kB
import re
import json
from openai import OpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.document_loaders import PyPDFLoader
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import ChatOpenAI
class AiService:
def __init__(self, model="gpt-4.1-mini"):
self.OPENAI_MODEL = model
self.embeddings = OpenAIEmbeddings(
model="text-embedding-3-small"
)
self.openai = OpenAI()
def generate_response(self, question_history=[], docs = [], extra_context: str = "", json_structure=None, instructions: str = None):
# simplified $SELECTION_PLACEHOLDER$
original_question = question_history[-1]["content"]
# attach supporting docs
if docs:
print(f"Found {len(docs)} supporting documents")
fragments = [str(d["payload"]) for d in docs]
question_history[-1]["content"] += "\n\nSupporting documents:\n" + "\n\n".join(fragments)
# attach extra context
if extra_context:
question_history[-1]["content"] += "\n\nExtra context:\n" + extra_context
try:
# common parameters
params = {
"instructions": instructions,
"input": question_history,
"model": self.OPENAI_MODEL,
"temperature": 0.0,
"top_p": 0.25
}
if json_structure:
params["text_format"] = json_structure
result = self.openai.responses.parse(**params)
content = result.output_parsed
else:
result = self.openai.responses.create(**params)
content = re.sub(r"\$", r"\\$", result.output_text)
return content
except Exception as e:
print(f"Error during API request: {e}")
return ""
finally:
# restore original question text
question_history[-1]["content"] = original_question
def generate_single_response(self, query, system_message, json_output=False, json_structure=None):
question_history = [{"role": "system", "content": system_message}, {"role": "user", "content": query}]
return self.generate_response(question_history, json_structure=json_structure)
def json_response_cleaner(self, response):
response = response.replace("\n", "").replace(
"\t", "").replace("\\", "")
return json.loads(response)
def init_messages(self, system_message):
return [{"role": "system", "content": system_message}]
def add_user_message(self, messages, user_message):
messages.append({"role": "user", "content": user_message})
return messages
def add_assistant_message(self, messages, assistant_message):
messages.append({"role": "assistant", "content": assistant_message})
return messages
def search_pdf(self, pdf_path, query, schema, output_format):
"""
Search through a PDF document and extract structured information.
Args:
pdf_path (str): Path to the PDF file
query (str): Search query
schema (dict): Schema defining the required output structure
Returns:
dict: Extracted structured information
"""
# Load and split the PDF
loader = PyPDFLoader(pdf_path)
pages = loader.load()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=100
)
splits = text_splitter.split_documents(pages)
combined_content = "\n".join([chunk.page_content for chunk in splits])
prompt = ChatPromptTemplate.from_template(
"""Extract the requested information from the following text, just write the answer to the question do not include that how the document discusses it or some other form of this. DIRECTLY ANSWER THE QUESTION.:
{text}
{schema}
Query: {query}"""
)
messages = prompt.format_messages(
text=combined_content,
schema=schema,
query=query
)
llm = ChatOpenAI(temperature=0, model=self.OPENAI_MODEL).with_structured_output(output_format)
response = llm.invoke(messages)
return response