backedn chat apis and uplaod apis integrated

This commit is contained in:
OwusuBlessing
2025-02-12 00:12:02 +01:00
parent 7200de4846
commit d1ed8b9e3f
4 changed files with 126 additions and 137 deletions
+35 -14
View File
@@ -78,7 +78,7 @@ async def get_api_key(api_key_header: str = Security(api_key_header)) -> str:
class ChatRequest(BaseModel):
resume_url: Optional[str] = None
query: str=None
conversation_id: str
chat_id: int
theme_id: Optional[int] = 1
full_history_url: Optional[str] = None
form_id:Optional[int] = None
@@ -95,7 +95,7 @@ class ChatResponse(BaseModel):
class GeneratePDFRequest(BaseModel):
resume_url: Optional[str] = None
conversation_id: str
chat_id: int
theme_id: Optional[int] = 1
full_history_url: Optional[str] = None
form_id:Optional[int] = None
@@ -215,7 +215,7 @@ async def chat_endpoint(
query = "Let's get started"
response = ai_chat(
query=query,
conversation_id=request.conversation_id,
conversation_id=request.chat_id,
theme_id=request.theme_id,
resume=resume_docs,
full_history=full_history_docs,
@@ -304,16 +304,16 @@ async def generate_pdf_endpoint(
# Here you would fetch the conversation data using the conversation_id
# This is a placeholder - replace with your actual conversation data fetching logic
# Get AI-generated theme content
# Get AI-generated theme content
response = ai_chat(
query="NOW GENERATE THE STARTPOP FRAMEWORK",
conversation_id=request.conversation_id,
conversation_id=request.chat_id,
theme_id=request.theme_id,
resume=resume_docs,
full_history=full_history_docs,
form_response=form_response_docs,
generate_theme="YES"
)
print(f"AI Response for theme: {response}")
# Ensure AI response is valid
@@ -321,19 +321,40 @@ async def generate_pdf_endpoint(
raise HTTPException(status_code=500, detail="Invalid AI response format")
# Generate PDF
response = json.loads(response)
pdf_content = create_pdf(response)
response_data = json.loads(response)
pdf_content = create_pdf(response_data)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"theme_{timestamp}.pdf"
file_path = f"theme_{timestamp}.pdf"
print(f"Returning PDF with filename: {filename}")
# Save the PDF locally temporarily
with open(file_path, "wb") as file:
file.write(pdf_content)
return Response(
content=pdf_content,
media_type="application/pdf",
headers={"Content-Disposition": f'attachment; filename="{filename}"'}
)
# Upload the PDF to S3 using the API
upload_url = f"{os.getenv('BACKEND_BASE_URL')}/v3/api/custom/theme/doc-upload?x-project={x_api_key}"
with open(file_path, 'rb') as file:
files = {'file': file}
upload_response = requests.post(upload_url, files=files)
# Check if the upload was successful
if upload_response.status_code != 200:
raise HTTPException(status_code=upload_response.status_code, detail="File upload to S3 failed: " + upload_response.text)
upload_data = upload_response.json() # Get the response in JSON format
# Extract the uploaded file URL
theme_url = upload_data.get("url") # Adjust this key based on the actual API response structure
if not theme_url:
raise HTTPException(status_code=500, detail="Failed to retrieve theme URL from upload response")
# Clean up the temporary file
os.remove(file_path)
# Return JSON response with theme URL and text
return {
"theme_url": theme_url,
"theme_text": response_data
}
except Exception as e:
print(f"Error generating theme: {str(e)}")
raise HTTPException(status_code=500, detail=f"Error: {str(e)}")
+52 -102
View File
@@ -7,16 +7,28 @@ from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage, BaseMessage
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import START, MessagesState, StateGraph
from utils.utils import format_questions_text
from src.prompts import chat_prompt
from langchain_openai import ChatOpenAI
from src.models import Phase2Generation,Phase1Generation
from config import TEMPERATURE
import os
import requests
import json
from dotenv import load_dotenv
from typing import List, Dict, Optional
from dataclasses import dataclass
from datetime import datetime
from langchain_core.messages import HumanMessage, AIMessage
# Load environment variables
load_dotenv()
@dataclass
class Message:
role: str # 'human' or 'ai'
content: str
timestamp: str
timestamp: str=None
QUESTIONS_PATH = "./data/config_files/questions.json"
with open(QUESTIONS_PATH, "r") as f:
@@ -46,63 +58,31 @@ def setup_prompt_template(theme: int, resume: str,full_history=None,form_respons
("system", chat_prompt(theme, resume,full_history,form_response,generate_theme)),
MessagesPlaceholder(variable_name="messages")
])
def fetch_conversation_history(conversation_id: str) -> List[Message]:
"""
Fetch conversation history from the API using the conversation ID.
"""
x_api_key = os.getenv("BACKEND_XAPI_KEY")
base_url = os.getenv("BACKEND_BASE_URL")
url = f"{base_url}/v3/api/custom/jordan/ai-chat/get-messages/{conversation_id}?x-project={x_api_key}"
def parse_ai_response(content: str) -> Dict:
"""Parse AI response content into expected format"""
try:
response = json.loads(content)
return {
"message": response.get("message", ""),
"end": response.get("end", "no") == "yes"
}
except json.JSONDecodeError:
return {
"message": content,
"end": False
}
response = requests.get(url)
response.raise_for_status() # Raise an error for bad responses
data = response.json()["data"] # First JSON parse
data = json.loads(json.loads(data))
# Parse the API response into Message objects
messages = []
for item in data:
role = item.get("role", "unknown")
content = item.get("content", "")
timestamp = datetime.now().isoformat() # Use current timestamp if not provided
messages.append(Message(role=role, content=content))
return messages
except requests.RequestException as e:
print(f"Error fetching conversation history: {e}")
return []
def add_message(storage_path: Path, conversation_id: str, role: str, content: str) -> None:
"""Add a message to the conversation history"""
message_data = {
"role": role,
"content": content,
"timestamp": datetime.now().isoformat()
}
conversations = load_conversations(storage_path)
if conversation_id not in conversations:
conversations[conversation_id] = {"messages": []}
conversations[conversation_id]["messages"].append(message_data)
save_conversations(storage_path, conversations)
def get_conversation_history(conversation_id: str, storage_path: Path) -> List[Message]:
"""Get the conversation history"""
conversations = load_conversations(storage_path)
if conversation_id not in conversations:
return None
return [
Message(
role=msg["role"],
content=msg["content"],
timestamp=msg["timestamp"]
)
for msg in conversations[conversation_id]["messages"]
]
def load_conversations(storage_path: Path) -> Dict:
"""Load conversations from storage file"""
try:
with open(storage_path, 'r') as f:
return json.load(f)
except FileNotFoundError:
return {}
def save_conversations(storage_path: Path, conversations: Dict) -> None:
"""Save conversations to storage file"""
with open(storage_path, 'w') as f:
json.dump(conversations, f, indent=2)
def convert_to_langchain_messages(messages: List[Message]) -> List[HumanMessage | AIMessage]:
"""Convert our Message objects to LangChain message objects"""
@@ -114,20 +94,19 @@ def convert_to_langchain_messages(messages: List[Message]) -> List[HumanMessage
converted_messages.append(AIMessage(content=msg.content))
return converted_messages
def ai_chat(query: str, conversation_id: str, theme_id: int, resume: str, full_history=None, form_response=None, generate_theme="NO") -> str:
"""Main chat function that processes queries and manages conversation"""
storage_path = Path("conversations.json")
class State(TypedDict):
messages: Annotated[Sequence[BaseMessage], "The messages in the conversation"]
messages: List[HumanMessage | AIMessage]
language: str
# Initialize model and workflow
model = ChatOpenAI(model=MODEL, temperature=TEMPERATURE)
if generate_theme == "YES":
model = model.with_structured_output(Phase2Generation)
else:
model = model.with_structured_output(Phase1Generation)
workflow = StateGraph(state_schema=State)
def call_model(state: State):
@@ -142,12 +121,11 @@ def ai_chat(query: str, conversation_id: str, theme_id: int, resume: str,full_hi
workflow.add_edge(START, "model")
workflow.add_node("model", call_model)
memory = MemorySaver()
app = workflow.compile(checkpointer=memory)
# Get conversation history
history = get_conversation_history(conversation_id, storage_path)
# Fetch conversation history from the API
history = fetch_conversation_history(conversation_id)
config = {"configurable": {"thread_id": conversation_id}}
language = "English"
@@ -155,65 +133,37 @@ def ai_chat(query: str, conversation_id: str, theme_id: int, resume: str,full_hi
if not history:
# New conversation
input_messages = [HumanMessage(content=query)] if query else [HumanMessage(content="Let's get started")]
output = app.invoke(
{"messages": input_messages, "language": language},
config
)
else:
# Existing conversation
history = convert_to_langchain_messages(history)
input_messages = history + [HumanMessage(content=query)] if query else history
output = app.invoke(
{"messages": input_messages, "language": language},
config
)
if generate_theme == "YES":
structured_message = output["messages"][0]
output = structured_message.json(by_alias=True) # This returns a JSON string.
print(f"Output: {output}")
if query:
add_message(storage_path, conversation_id, "human", query)
add_message(storage_path, conversation_id, "ai", output)
else:
structured_message = output["messages"][0]
output = structured_message.json() # This returns a JSON string.
output = json.loads(output)
print(output)
message = output.get("message")
print(output)
if query:
add_message(storage_path, conversation_id, "human", query)
add_message(storage_path, conversation_id, "ai", message)
print(output)
return output
# Example usage:
if __name__ == "__main__":
# Sample resume
sample_resume = """
John Doe
EMT-B Certified
5 years experience as volunteer firefighter
Bachelor's in Fire Science
"""
# Sample conversation
conversation_id = "12345"
theme_id = 1 # Customer Service theme
# Start conversation
# Continue conversation
follow_up = ai_chat(
query="What was my last questions?",
conversation_id=conversation_id,
theme_id=theme_id,
resume=sample_resume
)
print("AI:", follow_up)
#conversation_id = "12345" # Replace with the actual conversation ID
query = "Hello let us continue"
theme_id = 1
resume = "Emergency Response Specialist"
conversation_id = 1
response = ai_chat(query, conversation_id, theme_id, resume)
print(response)
+4 -1
View File
@@ -329,7 +329,7 @@ def chat_prompt(theme,resume,full_history=None, form_response=None,generate_them
NOTE: DO NOT KEEP THE CONVERSATION excessively long , CAREFULL ANALYZE USER RESUME AND THE PROVIDED EXAMPLES QUESTIONS AND ALL CONTEXT , ASK RELEVANT QUESTION BASED ON THE THEME AND THAT IS ALL
Follow these instructions exactly:
FOLLOW THESE INSTRUCTIONS STTRICTLY:
You may receive chat history that includes a previously generated STARTPOP framework, and the user may provide feedback on it. Use this feedback to engage with the user and ask clarifying questions as needed.
@@ -346,6 +346,9 @@ def chat_prompt(theme,resume,full_history=None, form_response=None,generate_them
If the user says, "I just want to make the actions a little bit clearer," a good response is: "Okay noted, would you like to generate your theme now?" (with the appropriate "end" and "pop_theme_generation" values).
If the user responds "yes," a good response is: "Go ahead and click on the theme generation button, thanks."
"NEVER RETURN THE STARTPOP FRAME WORK FORMAT PLEASE" , SEE EXAMPLE RESPONSES I GAVE
WHENE THERE IS THERE IS NEED TO GENERATE THE STARTPOP THEME FRAME , JUST TELL THEM TO GO AHEAD AND CLICK ON button
Strictly adhere to these guidelines
"""
return prompt
+21 -6
View File
@@ -1,13 +1,28 @@
import os
import requests
import json
from typing import List
from dotenv import load_dotenv
load_dotenv()
doc_id = 2
x_api_key = os.getenv("BACKEND_XAPI_KEY")
url = f"{os.getenv('BACKEND_BASE_URL')}/v3/api/custom/theme-document/answer/{doc_id}?x-project={x_api_key}"
result = requests.get(url)
response_json = result.json() # Return response in JSON format
print(response_json)
from src.llm import ai_chat
#conversation_id = "12345" # Replace with the actual conversation ID
query = "Hello let us continue"
theme_id = 1
resume = "Emergency Response Specialist"
conversation_id = 1
response = ai_chat(query, conversation_id, theme_id, resume)
print(response)
"""
with open(file_path, 'rb') as file:
files = {'file': file}
response = requests.post(upload_url, files=files)
response.raise_for_status() # Ensure we raise an error for bad responses
response_data = response.json() # Get the response in JSON format
print(response_data)
"""