Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 42 additions & 8 deletions app/chat_gpt_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,46 @@
import os
import logging
from typing import List
import agentops
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Initialize AgentOps
AGENTOPS_API_KEY = os.getenv("AGENTOPS_API_KEY")
if not AGENTOPS_API_KEY:
raise ValueError("AGENTOPS_API_KEY not found in environment variables")

agentops.init(AGENTOPS_API_KEY)
Comment on lines +9 to +17

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This initialization should happen in the app.py only, since it only needs to happen when the app is bootstrapped.

Suggested change
# Load environment variables
load_dotenv()
# Initialize AgentOps
AGENTOPS_API_KEY = os.getenv("AGENTOPS_API_KEY")
if not AGENTOPS_API_KEY:
raise ValueError("AGENTOPS_API_KEY not found in environment variables")
agentops.init(AGENTOPS_API_KEY)


CHAT_GPT_DEFAULT_MODEL = os.getenv("CHAT_GPT_MODEL", "gpt-4o")
CHAT_GPT_DEFAULT_TEMPERATURE = float(os.getenv("CHAT_GPT_TEMPERATURE", "0.7"))
CHAT_GPT_DEFAULT_MAX_TOKENS = int(os.getenv("CHAT_GPT_MAX_TOKENS", "1500"))


class MessageRole(str, Enum):
user = "user"
assistant = "assistant"
system = "system"


class Message(BaseModel):
role: MessageRole
content: str


# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Configure OpenAI client
client = AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY"))
if not client.api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables")
@agentops.record_function('configure_openai_client')
def configure_openai_client():
client = AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY"))
if not client.api_key:
raise ValueError("OPENAI_API_KEY not found in environment variables")
return client

client = configure_openai_client()

@agentops.record_function('get_chat_response_with_history')
async def get_chat_response_with_history(
messages: List[Message],
system_prompt: str = "You are a helpful assistant that always answers questions.",
Expand Down Expand Up @@ -60,5 +72,27 @@ async def get_chat_response_with_history(
)
return response.choices[0].message.content.strip()
except Exception as e:
logger.error(f"OpenAI API error: {str(e)}")
error_message = f"OpenAI API error: {str(e)}"
logger.error(error_message)
agentops.log_error(error_message)
return f"I'm sorry, but I encountered an error: {str(e)}"

@agentops.record_function('main')
async def main():
# Example usage
messages = [
Message(role=MessageRole.user, content="Hello, how are you?"),
Message(role=MessageRole.assistant, content="I'm doing well, thank you for asking. How can I assist you today?"),
Message(role=MessageRole.user, content="Can you tell me about the weather?"),
]
response = await get_chat_response_with_history(messages)
print(f"Assistant's response: {response}")

if __name__ == "__main__":
import asyncio
try:
asyncio.run(main())
except Exception as e:
agentops.log_error(str(e))
finally:
agentops.end_session('Success')
136 changes: 75 additions & 61 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import List, Dict
import markdown2
import uuid
import agentops

from app.chat_gpt_client import get_chat_response_with_history, Message, MessageRole
from app.rag_service import RAGService
Expand All @@ -15,45 +16,47 @@
# Load environment variables
load_dotenv()

# Load configuration from environment variables with default values
CHAT_TITLE = os.getenv(
"CHAT_TITLE",
"AI Chat Assistant",
)
WELCOME_MESSAGE = os.getenv(
"WELCOME_MESSAGE",
"Welcome! How can I assist you today?",
)
SYSTEM_PROMPT = os.getenv(
"SYSTEM_PROMPT",
"You are a helpful assistant that answers questions based on the given context and chat history.",
)
# TODO: Move this to be a Pydantc Field on the AstraDBStore (AstraDBConfig?)
ASTRA_COLLECTION_NAME = os.getenv("ASTRA_COLLECTION_NAME")
# Initialize AgentOps
AGENTOPS_API_KEY = os.getenv("AGENTOPS_API_KEY")
if not AGENTOPS_API_KEY:
raise ValueError("AGENTOPS_API_KEY not found in environment variables")

agentops.init(AGENTOPS_API_KEY)

app = FastAPI()
# Load configuration from environment variables with default values
CHAT_TITLE = os.getenv("CHAT_TITLE", "AI Chat Assistant")
WELCOME_MESSAGE = os.getenv("WELCOME_MESSAGE", "Welcome! How can I assist you today?")
SYSTEM_PROMPT = os.getenv("SYSTEM_PROMPT", "You are a helpful assistant that answers questions based on the given context and chat history.")
ASTRA_COLLECTION_NAME = os.getenv("ASTRA_COLLECTION_NAME")

templates_directory = os.path.join(os.path.dirname(__file__), "templates")
templates = Jinja2Templates(directory=templates_directory)
@agentops.record_function('create_app')
def create_app():
app = FastAPI()

templates_directory = os.path.join(os.path.dirname(__file__), "templates")
templates = Jinja2Templates(directory=templates_directory)

static_directory = os.path.join(os.path.dirname(__file__), "static")
app.mount("/static", StaticFiles(directory=static_directory), name="static")

return app, templates

# Mount the static directory
static_directory = os.path.join(os.path.dirname(__file__), "static")
app.mount("/static", StaticFiles(directory=static_directory), name="static")
app, templates = create_app()

# Simulating a database with an in-memory list
chat_history: List[Message] = []

# Get the absolute path to the project root
project_root = os.path.dirname(os.path.abspath(__file__))

# Initialize RAG service with ChromaDBStore
chroma_db_path = os.path.join(project_root, "db")
vector_store = AstraDBStore(collection_name=ASTRA_COLLECTION_NAME)
rag_service = RAGService(vector_store)
@agentops.record_function('initialize_rag_service')
def initialize_rag_service():
chroma_db_path = os.path.join(project_root, "db")
vector_store = AstraDBStore(collection_name=ASTRA_COLLECTION_NAME)
return RAGService(vector_store)

rag_service = initialize_rag_service()

@app.get("/", response_class=HTMLResponse)
@agentops.record_function('read_root')
async def read_root(request: Request) -> HTMLResponse:
return templates.TemplateResponse(
"chat.html",
Expand All @@ -64,48 +67,59 @@ async def read_root(request: Request) -> HTMLResponse:
},
)


@app.post("/chat")
@agentops.record_function('chat')
async def chat(request: Request, message: str = Form(...)) -> HTMLResponse:
# Prepare messages with the correct order
prepared_messages, citations = await rag_service.prepare_messages_with_sources(
system_prompt=f"<system-prompt>{SYSTEM_PROMPT}</system-prompt>",
chat_history=chat_history[-5:], # Last 5 messages for context
user_message=message,
)

# Get response from ChatGPT using prepared messages
bot_response = await get_chat_response_with_history(prepared_messages)

# Render Markdown to HTML (with safety features)
bot_response_html = markdown2.markdown(bot_response, safe_mode="escape")

# Add user message and bot response to chat history
chat_history.append(Message(role=MessageRole.user, content=message))
chat_history.append(Message(role=MessageRole.assistant, content=bot_response))

message_id = str(uuid.uuid4())

response_html = templates.TemplateResponse(
"bot_message.html",
{
"request": request,
"bot_response_html": bot_response_html,
"citations": citations,
"message_id": message_id,
},
)

return response_html

try:
prepared_messages, citations = await rag_service.prepare_messages_with_sources(
system_prompt=f"<system-prompt>{SYSTEM_PROMPT}</system-prompt>",
chat_history=chat_history[-5:],
user_message=message,
)

bot_response = await get_chat_response_with_history(prepared_messages)
bot_response_html = markdown2.markdown(bot_response, safe_mode="escape")

chat_history.append(Message(role=MessageRole.user, content=message))
chat_history.append(Message(role=MessageRole.assistant, content=bot_response))

message_id = str(uuid.uuid4())

response_html = templates.TemplateResponse(
"bot_message.html",
{
"request": request,
"bot_response_html": bot_response_html,
"citations": citations,
"message_id": message_id,
},
)

return response_html
except Exception as e:
agentops.log_error(f"Error in chat endpoint: {str(e)}")
raise

@app.get("/api/chat_history")
@agentops.record_function('get_chat_history')
async def get_chat_history() -> List[Dict[str, str]]:
return [message.model_dump() for message in chat_history]


# Optional: Add a route to clear chat history (for testing/demo purposes)
@app.post("/api/clear_history")
@agentops.record_function('clear_history')
async def clear_history() -> Dict[str, str]:
chat_history.clear()
return {"message": "Chat history cleared"}

@agentops.record_function('main')
def main():
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)

if __name__ == "__main__":
try:
main()
except Exception as e:
agentops.log_error(str(e))
finally:
agentops.end_session('Success')
Loading