I’m working on a chatbot that uses AWS Lex with Langchain. I managed to store chat history in session_attributes[‘sessionContext’] and it works fine. When I check the logs, I can see the conversation history is properly saved in session_attributes[‘sessionContext’]. However, there’s an issue with the {history} parameter in my prompt template. It only shows the current message from Lex instead of the full conversation history. I need to figure out how to pass the session_attributes data as the history parameter in my prompt.
import json
import logging
from langchain.llms import SagemakerEndpoint
from langchain.retrievers import KendraIndexRetriever
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
from langchain.memory import ConversationBufferMemory
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
def finish_conversation(session_attrs, context_data, state, user_intent, response_msg):
result = {
'sessionState': {
'activeContexts':[{
'name': 'mainContext',
'contextAttributes': context_data,
'timeToLive': {
'timeToLiveInSeconds': 500,
'turnsToLive': 1
}
}],
'sessionAttributes': session_attrs,
'dialogAction': {
'type': 'Close',
},
'intent': user_intent,
},
'messages': [{'contentType': 'PlainText', 'content': response_msg}]
}
return result
def continue_dialog(session_attrs, context_data, user_intent, response_msg):
return {
'sessionState': {
'activeContexts':[{
'name': 'mainContext',
'contextAttributes': context_data,
'timeToLive': {
'timeToLiveInSeconds': 500,
'turnsToLive': 1
}
}],
'sessionAttributes': session_attrs,
'dialogAction': {
'type': 'Delegate',
},
'intent': user_intent,
},
'messages': [{'contentType': 'PlainText', 'content': response_msg}]
}
def get_slot_value(slot_data):
if slot_data is not None:
return slot_data['value']['interpretedValue']
else:
return None
def call_ai_model(user_question, chat_history):
model_endpoint = 'my-sagemaker-endpoint'
aws_region = 'us-west-2'
search_index = 'my-kendra-index'
print("AI model chat history: ", chat_history)
class ResponseHandler(ContentHandlerBase):
content_type = "application/json"
accepts = "application/json"
def transform_input(self, input_text: str, params: dict) -> bytes:
payload = json.dumps({"text_inputs": input_text, **params})
return payload.encode('utf-8')
def transform_output(self, model_output: bytes) -> str:
result = json.loads(model_output.read().decode("utf-8"))
return result["generated_texts"][0]
handler = ResponseHandler()
language_model = SagemakerEndpoint(
endpoint_name=model_endpoint,
region_name=aws_region,
model_kwargs={"temperature": 1e-10, "max_length": 400},
content_handler=handler
)
document_retriever = KendraIndexRetriever(
kendraindex=search_index,
awsregion=aws_region,
return_source_documents=True
)
prompt_template = """
Based on the provided context (in <context></context> tags) and previous conversation (in <chat></chat> tags), answer the user's question:
------
<context>
{context}
</context>
------
<chat>
{history}
</chat>
------
Question: {question}
Response:
"""
qa_prompt = PromptTemplate(
input_variables=["history", "context", "question"],
template=prompt_template
)
qa_chain = RetrievalQA.from_chain_type(
llm=language_model,
chain_type='stuff',
retriever=document_retriever,
verbose=True,
chain_type_kwargs={
"verbose": True,
"prompt": qa_prompt,
"memory": ConversationBufferMemory(
memory_key="history",
input_key="question",
return_messages=True
),
}
)
final_result = qa_chain({'query': user_question, 'history': chat_history})
ai_response = qa_chain(user_question)
print("Final answer: ", ai_response['result'])
return ai_response
def main_handler(lex_request, lambda_context):
print("Received request: ", lex_request)
logger.debug(lex_request)
current_intent = lex_request['sessionState']['intent']
session_attrs = lex_request['sessionState']['sessionAttributes']
if 'sessionContext' not in session_attrs.keys():
print("Starting new session")
session_attrs['sessionContext'] = ''
context_info = {}
if current_intent['name'] == 'FallbackIntent':
user_input = lex_request['inputTranscript'] + session_attrs['sessionContext']
ai_result = call_ai_model(user_input, session_attrs['sessionContext'])
result_data = json.dumps({
'Response': ai_result['result'],
})
context_info['UserQuery'] = result_data
logger.debug('AI Response={}'.format(result_data))
current_intent['confirmationState'] = "Confirmed"
current_intent['state'] = "Fulfilled"
session_attrs['sessionContext'] = session_attrs['sessionContext'] + ' ' + lex_request['inputTranscript'] + ' ' + ai_result['result']
print("Updated history: ", session_attrs['sessionContext'])
return finish_conversation(session_attrs, context_info, 'Fulfilled', current_intent, ai_result['result'])
user_query = get_slot_value(lex_request['sessionState']['intent']['slots']['Query'])
print("User's question: ", user_query)
if user_query or current_intent['name'] == 'FallbackIntent':
ai_result = call_ai_model(user_query, session_attrs['sessionContext'])
result_data = json.dumps({
'Response': ai_result['result'],
})
logger.debug('AI Response={}'.format(result_data))
current_intent['confirmationState'] = "Confirmed"
current_intent['state'] = "Fulfilled"
session_attrs['sessionContext'] = session_attrs['sessionContext'] + ' ' + lex_request['inputTranscript'] + ' ' + ai_result['result']
print("Updated history: ", session_attrs['sessionContext'])
return finish_conversation(session_attrs, context_info, 'Fulfilled', current_intent, ai_result['result'])