Adil/fix salman docs (#75)

* added the first set of docs for our technical docs

* more docuemtnation changes

* added support for prompt processing and updated life of a request

* updated docs to including getting help sections and updated life of a request

* committing local changes for getting started guide, sample applications, and full reference spec for prompt-config

* updated configuration reference, added sample app skeleton, updated favico

* fixed the configuration refernce file, and made minor changes to the intent detection. commit v1 for now

* Updated docs with use cases and example code, updated what is arch, and made minor changes throughout

* fixed imaged and minor doc fixes

* add sphinx_book_theme

* updated README, and make some minor fixes to documetnation

* fixed README.md

* fixed image width

---------

Co-authored-by: Salman Paracha <salmanparacha@MacBook-Pro-261.local>
Co-authored-by: Adil Hafeez <adil@katanemo.com>
This commit is contained in:
Salman Paracha 2024-09-24 13:54:17 -07:00 committed by GitHub
parent 2d31aeaa36
commit 13dff3089d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 931 additions and 287 deletions

View file

@ -1,78 +1,96 @@
from flask import Flask, request, jsonify
from datetime import datetime
import uuid
from langchain.memory import ConversationBufferMemory
from langchain.schema import AIMessage, HumanMessage
from langchain import OpenAI
app = Flask(__name__)
# Global dictionary to keep track of user conversations
user_conversations = {}
# Global dictionary to keep track of user memories
user_memories = {}
def get_user_conversation(user_id):
"""
Retrieve the user's conversation history.
If the user does not exist, initialize their conversation data.
Retrieve the user's conversation memory using LangChain.
If the user does not exist, initialize their conversation memory.
"""
if user_id not in user_conversations:
user_conversations[user_id] = {
'messages': []
}
return user_conversations[user_id]
if user_id not in user_memories:
user_memories[user_id] = ConversationBufferMemory(return_messages=True)
return user_memories[user_id]
def update_user_conversation(user_id, client_messages, intent_changed):
"""
Update the user's conversation history with new messages.
Update the user's conversation memory with new messages using LangChain.
Each message is augmented with a UUID, timestamp, and intent change marker.
Only new messages are added to avoid duplication.
"""
user_data = get_user_conversation(user_id)
# Existing messages in the user's conversation
stored_messages = user_data['messages']
memory = get_user_conversation(user_id)
stored_messages = memory.chat_memory.messages
# Determine the number of stored messages
num_stored_messages = len(stored_messages)
# Check for out-of-sync messages
if num_stored_messages > len(client_messages):
return jsonify({'error': 'Client messages are out of sync with server'}), 400
# Determine new messages by slicing the client messages
new_messages = client_messages[num_stored_messages:]
# Process each new message
for index, message in enumerate(new_messages):
message_entry = {
role = message.get('role')
content = message.get('content')
metadata = {
'uuid': str(uuid.uuid4()),
'timestamp': datetime.utcnow().isoformat(),
'role': message.get('role'),
'content': message.get('content'),
'intent_changed': False # Default value
}
# Mark the intent change on the last message if detected
if intent_changed and index == len(new_messages) - 1:
message_entry['intent_changed'] = True
user_data['messages'].append(message_entry)
metadata['intent_changed'] = True
return user_data
# Create a new message with metadata
if role == 'user':
memory.chat_memory.add_message(
HumanMessage(content=content, additional_kwargs={'metadata': metadata})
)
elif role == 'assistant':
memory.chat_memory.add_message(
AIMessage(content=content, additional_kwargs={'metadata': metadata})
)
else:
# Handle other roles if necessary
pass
return memory
def get_messages_since_last_intent(messages):
"""
Retrieve messages from the last intent change onwards.
Retrieve messages from the last intent change onwards using LangChain.
"""
messages_since_intent = []
for message in reversed(messages):
# Insert message at the beginning to maintain correct order
messages_since_intent.insert(0, message)
if message.get('intent_changed'):
metadata = message.additional_kwargs.get('metadata', {})
# Break if intent_changed is True
if metadata.get('intent_changed', False) == True:
break
return messages_since_intent
def forward_to_llm(messages):
"""
Simulate forwarding messages to an upstream LLM.
Replace this with the actual API call to the LLM.
Forward messages to an upstream LLM using LangChain.
"""
# For demonstration purposes, we'll return a placeholder response
return "LLM response based on provided messages."
# Convert messages to a conversation string
conversation = ""
for message in messages:
role = 'User' if isinstance(message, HumanMessage) else 'Assistant'
content = message.content
conversation += f"{role}: {content}\n"
# Use LangChain's LLM to get a response. This call is proxied through Arch for end-to-end observability and traffic management
llm = OpenAI()
# Create a prompt that includes the conversation
prompt = f"{conversation}Assistant:"
response = llm(prompt)
return response
@app.route('/process_rag', methods=['POST'])
def process_rag():
@ -98,22 +116,37 @@ def process_rag():
return jsonify({'error': 'Invalid value for x-arch-prompt-intent-change header'}), 400
# Update user conversation based on intent change
user_data = update_user_conversation(user_id, client_messages, intent_changed)
memory = update_user_conversation(user_id, client_messages, intent_changed)
# Retrieve messages since last intent change for LLM
messages_for_llm = get_messages_since_last_intent(user_data['messages'])
messages_for_llm = get_messages_since_last_intent(memory.chat_memory.messages)
# Forward messages to upstream LLM
llm_response = forward_to_llm(messages_for_llm)
# Prepare the messages to return
messages_to_return = []
for message in memory.chat_memory.messages:
role = 'user' if isinstance(message, HumanMessage) else 'assistant'
content = message.content
metadata = message.additional_kwargs.get('metadata', {})
message_entry = {
'uuid': metadata.get('uuid'),
'timestamp': metadata.get('timestamp'),
'role': role,
'content': content,
'intent_changed': metadata.get('intent_changed', False)
}
messages_to_return.append(message_entry)
# Prepare the response
response = {
'user_id': user_id,
'messages': user_data['messages'],
'messages': messages_to_return,
'llm_response': llm_response
}
return jsonify(response), 200
if __name__ == '__main__':
app.run(debug=True)
app.run(debug=True)