| import os |
| import chainlit as cl |
| from dotenv import load_dotenv |
| from langchain_anthropic import ChatAnthropic |
| from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder |
| from langchain_core.output_parsers import StrOutputParser |
| from langchain_core.chat_history import InMemoryChatMessageHistory |
|
|
| |
| load_dotenv() |
|
|
| |
| ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY") |
| if not ANTHROPIC_API_KEY: |
| print("WARNING: ANTHROPIC_API_KEY not found in environment variables!") |
|
|
| |
|
|
|
|
| def load_system_prompt(): |
| """Load the system prompt from prompt.md file.""" |
| try: |
| with open("prompt.md", "r", encoding="utf-8") as f: |
| prompt_content = f.read() |
| |
| if len(prompt_content) < 100: |
| print("WARNING: prompt.md seems too short. Using fallback prompt.") |
| return "You are an Adaptive Coach guiding a small team through the Design Thinking process." |
| return prompt_content |
| except FileNotFoundError: |
| print("WARNING: prompt.md not found. Using fallback prompt.") |
| return "You are an Adaptive Coach guiding a small team through the Design Thinking process." |
| except UnicodeDecodeError as e: |
| print( |
| f"WARNING: Encoding error reading prompt.md: {e}. Using fallback prompt.") |
| return "You are an Adaptive Coach guiding a small team through the Design Thinking process." |
|
|
|
|
| |
| SYSTEM_PROMPT = load_system_prompt() |
|
|
|
|
| def get_chain(): |
| """Create and return the LCEL chain with conversation history support.""" |
| if not ANTHROPIC_API_KEY: |
| return None |
|
|
| |
| model = ChatAnthropic( |
| model="claude-sonnet-4-5-20250929", |
| streaming=True, |
| temperature=0.7 |
| ) |
|
|
| |
| |
| prompt = ChatPromptTemplate.from_messages([ |
| ("system", SYSTEM_PROMPT), |
| MessagesPlaceholder(variable_name="chat_history"), |
| ("human", "{input}") |
| ]) |
|
|
| |
| return prompt | model | StrOutputParser() |
|
|
|
|
| @cl.on_chat_start |
| async def on_chat_start(): |
| """Initialize the chain when a chat session starts.""" |
| |
| chat_history = InMemoryChatMessageHistory() |
| cl.user_session.set("chat_history", chat_history) |
|
|
| |
| cl.user_session.set("first_message", True) |
|
|
| |
| |
| try: |
| if ANTHROPIC_API_KEY: |
| welcome_msg = "What are you working on?" |
| await cl.Message(content=welcome_msg).send() |
|
|
| |
| from langchain_core.messages import AIMessage |
| chat_history.add_message(AIMessage(content=welcome_msg)) |
| cl.user_session.set("chat_history", chat_history) |
|
|
| |
| cl.user_session.set("welcome_sent", True) |
| except (LookupError, RuntimeError, Exception) as e: |
| |
| print(f"Could not send welcome message in on_chat_start: {e}") |
| cl.user_session.set("welcome_sent", False) |
|
|
|
|
| def is_simple_greeting(text: str) -> bool: |
| """Check if the message is just a simple greeting.""" |
| text_lower = text.strip().lower() |
| simple_greetings = ["hi", "hello", "hey", |
| "hey there", "hi there", "greetings"] |
| return text_lower in simple_greetings or len(text_lower) <= 3 |
|
|
|
|
| @cl.on_message |
| async def on_message(message: cl.Message): |
| """Handle incoming messages and stream responses.""" |
| |
| chat_history = cl.user_session.get("chat_history") |
| if chat_history is None: |
| chat_history = InMemoryChatMessageHistory() |
| cl.user_session.set("chat_history", chat_history) |
|
|
| |
| is_first = cl.user_session.get("first_message", False) |
| welcome_sent = cl.user_session.get("welcome_sent", False) |
|
|
| if is_first: |
| cl.user_session.set("first_message", False) |
|
|
| |
| if not ANTHROPIC_API_KEY: |
| await cl.Message( |
| content="❌ Error: ANTHROPIC_API_KEY not configured. Please set it in Space settings → Variables and secrets." |
| ).send() |
| return |
|
|
| |
| if not welcome_sent: |
| welcome_msg = "What are you working on?" |
| await cl.Message(content=welcome_msg).send() |
|
|
| |
| from langchain_core.messages import AIMessage |
| chat_history.add_message(AIMessage(content=welcome_msg)) |
| |
| cl.user_session.set("chat_history", chat_history) |
|
|
| |
| |
| if is_simple_greeting(message.content): |
| return |
|
|
| |
| if not ANTHROPIC_API_KEY: |
| await cl.Message( |
| content="❌ Error: ANTHROPIC_API_KEY not configured. Please set it in Space settings → Variables and secrets." |
| ).send() |
| return |
|
|
| |
| chain = get_chain() |
| if chain is None: |
| await cl.Message(content="❌ Error: Chain not initialized. Please refresh the page.").send() |
| return |
|
|
| |
| msg = cl.Message(content="") |
| await msg.send() |
|
|
| |
| input_dict = { |
| "input": message.content, |
| "chat_history": chat_history.messages |
| } |
|
|
| |
| try: |
| full_response = "" |
| async for chunk in chain.astream(input_dict): |
| await msg.stream_token(chunk) |
| full_response += chunk |
| await msg.update() |
|
|
| |
| from langchain_core.messages import HumanMessage, AIMessage |
| chat_history.add_message(HumanMessage(content=message.content)) |
| chat_history.add_message(AIMessage(content=full_response)) |
|
|
| |
| cl.user_session.set("chat_history", chat_history) |
|
|
| except Exception as e: |
| |
| error_msg = f"❌ Error: {str(e)}" |
| print(f"Error in on_message: {error_msg}") |
| import traceback |
| traceback.print_exc() |
| await cl.Message( |
| content=f"{error_msg}\n\nPlease check the Space logs for more details." |
| ).send() |
|
|