sumedhphadke commited on
Commit
799d239
·
1 Parent(s): 43de7ff

Fixed chat history

Browse files
Files changed (2) hide show
  1. app.py +80 -44
  2. requirements.txt +7 -6
app.py CHANGED
@@ -2,8 +2,9 @@ import os
2
  import chainlit as cl
3
  from dotenv import load_dotenv
4
  from langchain_anthropic import ChatAnthropic
5
- from langchain_core.prompts import ChatPromptTemplate
6
  from langchain_core.output_parsers import StrOutputParser
 
7
 
8
  # Load environment variables (Hugging Face Spaces injects secrets automatically)
9
  load_dotenv()
@@ -40,7 +41,7 @@ SYSTEM_PROMPT = load_system_prompt()
40
 
41
 
42
  def get_chain():
43
- """Create and return the LCEL chain."""
44
  if not ANTHROPIC_API_KEY:
45
  return None
46
 
@@ -51,9 +52,11 @@ def get_chain():
51
  temperature=0.7
52
  )
53
 
54
- # Create the prompt template with system message from prompt.md
 
55
  prompt = ChatPromptTemplate.from_messages([
56
  ("system", SYSTEM_PROMPT),
 
57
  ("human", "{input}")
58
  ])
59
 
@@ -64,66 +67,99 @@ def get_chain():
64
  @cl.on_chat_start
65
  async def on_chat_start():
66
  """Initialize the chain when a chat session starts."""
67
- # Store the chain in user session first (before any messages)
68
- chain = get_chain()
69
- if chain:
70
- cl.user_session.set("chain", chain)
71
 
72
- # Check if API key is available
73
- if not ANTHROPIC_API_KEY:
74
- try:
75
- await cl.Message(
76
- content="❌ Error: ANTHROPIC_API_KEY not configured. Please set it in Space settings → Variables and secrets."
77
- ).send()
78
- except LookupError:
79
- # ContextVar error - chain will be initialized on first message instead
80
- pass
81
- return
82
 
83
- # Create the chain if not already created
84
- if chain is None:
85
- try:
86
- await cl.Message(
87
- content="❌ Error: Could not initialize chain. Please check API key configuration."
88
- ).send()
89
- except LookupError:
90
- # ContextVar error - chain will be initialized on first message instead
91
- pass
92
- return
93
 
94
- # Send welcome message - according to prompt section 1.6, ask ONE question: "What are you working on?"
95
- try:
96
- await cl.Message(content="What are you working on?").send()
97
- except LookupError:
98
- # ContextVar error - message will be sent on first user message instead
99
- # The chain is already stored in user_session, so on_message will work
100
- pass
101
 
102
 
103
  @cl.on_message
104
  async def on_message(message: cl.Message):
105
  """Handle incoming messages and stream responses."""
106
- # Retrieve the chain from user session
107
- chain = cl.user_session.get("chain")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
- # If chain is None, try to initialize it (in case on_chat_start had ContextVar issues)
110
- if chain is None:
111
- chain = get_chain()
112
- if chain:
113
- cl.user_session.set("chain", chain)
114
- else:
115
- await cl.Message(content="Error: Chain not initialized. Please refresh the page.").send()
 
 
 
 
 
116
  return
117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  # Create a message object for streaming
119
  msg = cl.Message(content="")
120
  await msg.send()
121
 
 
 
 
 
 
 
122
  # Invoke the chain asynchronously with streaming
123
  try:
124
- async for chunk in chain.astream({"input": message.content}):
 
125
  await msg.stream_token(chunk)
 
126
  await msg.update()
 
 
 
 
 
 
 
 
 
127
  except Exception as e:
128
  # Log the full error for debugging
129
  error_msg = f"❌ Error: {str(e)}"
 
2
  import chainlit as cl
3
  from dotenv import load_dotenv
4
  from langchain_anthropic import ChatAnthropic
5
+ from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
6
  from langchain_core.output_parsers import StrOutputParser
7
+ from langchain_core.chat_history import InMemoryChatMessageHistory
8
 
9
  # Load environment variables (Hugging Face Spaces injects secrets automatically)
10
  load_dotenv()
 
41
 
42
 
43
  def get_chain():
44
+ """Create and return the LCEL chain with conversation history support."""
45
  if not ANTHROPIC_API_KEY:
46
  return None
47
 
 
52
  temperature=0.7
53
  )
54
 
55
+ # Create the prompt template with system message and conversation history placeholder
56
+ # Always include MessagesPlaceholder - we'll pass empty list if no history
57
  prompt = ChatPromptTemplate.from_messages([
58
  ("system", SYSTEM_PROMPT),
59
+ MessagesPlaceholder(variable_name="chat_history"),
60
  ("human", "{input}")
61
  ])
62
 
 
67
  @cl.on_chat_start
68
  async def on_chat_start():
69
  """Initialize the chain when a chat session starts."""
70
+ # Initialize chat history for this session
71
+ chat_history = InMemoryChatMessageHistory()
72
+ cl.user_session.set("chat_history", chat_history)
 
73
 
74
+ # Mark that this is a new session (for welcome message)
75
+ cl.user_session.set("first_message", True)
 
 
 
 
 
 
 
 
76
 
77
+ # Don't send messages here to avoid ContextVar issues in deployment
78
+ # Messages will be handled in on_message instead
 
 
 
 
 
 
 
 
79
 
80
+
81
+ def is_simple_greeting(text: str) -> bool:
82
+ """Check if the message is just a simple greeting."""
83
+ text_lower = text.strip().lower()
84
+ simple_greetings = ["hi", "hello", "hey",
85
+ "hey there", "hi there", "greetings"]
86
+ return text_lower in simple_greetings or len(text_lower) <= 3
87
 
88
 
89
  @cl.on_message
90
  async def on_message(message: cl.Message):
91
  """Handle incoming messages and stream responses."""
92
+ # Get or initialize chat history
93
+ chat_history = cl.user_session.get("chat_history")
94
+ if chat_history is None:
95
+ chat_history = InMemoryChatMessageHistory()
96
+ cl.user_session.set("chat_history", chat_history)
97
+
98
+ # Check if this is the first message and send welcome message
99
+ is_first = cl.user_session.get("first_message", False)
100
+ if is_first:
101
+ cl.user_session.set("first_message", False)
102
+
103
+ # Check API key
104
+ if not ANTHROPIC_API_KEY:
105
+ await cl.Message(
106
+ content="❌ Error: ANTHROPIC_API_KEY not configured. Please set it in Space settings → Variables and secrets."
107
+ ).send()
108
+ return
109
 
110
+ # Send welcome message - according to prompt section 1.6, ask ONE question: "What are you working on?"
111
+ welcome_msg = "What are you working on?"
112
+ await cl.Message(content=welcome_msg).send()
113
+
114
+ # Add welcome message to chat history and persist back to session
115
+ from langchain_core.messages import AIMessage
116
+ chat_history.add_message(AIMessage(content=welcome_msg))
117
+ cl.user_session.set("chat_history", chat_history) # Persist changes
118
+
119
+ # If the user's first message is just a greeting, don't process it
120
+ # Otherwise, continue to process their meaningful response
121
+ if is_simple_greeting(message.content):
122
  return
123
 
124
+ # Check API key
125
+ if not ANTHROPIC_API_KEY:
126
+ await cl.Message(
127
+ content="❌ Error: ANTHROPIC_API_KEY not configured. Please set it in Space settings → Variables and secrets."
128
+ ).send()
129
+ return
130
+
131
+ # Get the chain (it supports conversation history via MessagesPlaceholder)
132
+ chain = get_chain()
133
+ if chain is None:
134
+ await cl.Message(content="❌ Error: Chain not initialized. Please refresh the page.").send()
135
+ return
136
+
137
  # Create a message object for streaming
138
  msg = cl.Message(content="")
139
  await msg.send()
140
 
141
+ # Prepare input with chat history (previous messages only, current message goes in {input})
142
+ input_dict = {
143
+ "input": message.content,
144
+ "chat_history": chat_history.messages # All previous messages
145
+ }
146
+
147
  # Invoke the chain asynchronously with streaming
148
  try:
149
+ full_response = ""
150
+ async for chunk in chain.astream(input_dict):
151
  await msg.stream_token(chunk)
152
+ full_response += chunk
153
  await msg.update()
154
+
155
+ # Add both user message and assistant response to chat history AFTER processing
156
+ from langchain_core.messages import HumanMessage, AIMessage
157
+ chat_history.add_message(HumanMessage(content=message.content))
158
+ chat_history.add_message(AIMessage(content=full_response))
159
+
160
+ # Persist changes back to session
161
+ cl.user_session.set("chat_history", chat_history)
162
+
163
  except Exception as e:
164
  # Log the full error for debugging
165
  error_msg = f"❌ Error: {str(e)}"
requirements.txt CHANGED
@@ -1,6 +1,7 @@
1
- chainlit
2
- langchain
3
- langchain-anthropic
4
- python-dotenv
5
- pydantic
6
- websockets
 
 
1
+ chainlit>=2.9.4
2
+ langchain>=1.2.0
3
+ langchain-anthropic>=1.3.0
4
+ python-dotenv>=1.0.1
5
+ pydantic>=2.12.0
6
+ websockets>=15.0
7
+ typing-extensions>=4.15.0