reo_first / app.py
ritam678
Initial commit with project files
3e9aaf1
raw
history blame contribute delete
No virus
9.21 kB
import os
import spacy
# import tiktoken
from openai import OpenAI
from datetime import datetime
from spacy.matcher import Matcher
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
import streamlit as st
from langchain_core.prompts import PromptTemplate
from langchain.chains import RetrievalQA, ConversationalRetrievalChain
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import CharacterTextSplitter, RecursiveCharacterTextSplitter
from langchain.memory import ConversationBufferMemory
from langchain.prompts import PromptTemplate
from langchain_community.document_loaders import DirectoryLoader
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler # for streaming response
from langchain.callbacks.manager import CallbackManager
nlp = spacy.load("en_core_web_sm")
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
USER_AVATAR = "👤"
BOT_AVATAR = "🤖"
callback_manager = CallbackManager([StreamingStdOutCallbackHandler()])
# Load the .env file
load_dotenv()
OPENAI_API_KEY = os.getenv('api_key')
loaders = [DirectoryLoader('input', show_progress=True),
DirectoryLoader('customer_files', show_progress=True)]
docs = []
for loader in loaders:
docs.extend(loader.load())
# len(docs)
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
texts = text_splitter.split_documents(docs)
embeddings = OpenAIEmbeddings(model="text-embedding-3-large", api_key = OPENAI_API_KEY)
db = FAISS.from_documents(texts, embeddings)
llm = ChatOpenAI(model="gpt-4o", temperature=0, api_key=OPENAI_API_KEY)
retriever_from_llm = MultiQueryRetriever.from_llm(
retriever=db.as_retriever(search_kwargs={"k":10}), llm=llm
)
# db.save_local("vector-store")
# db = FAISS.load_local("vector-store", embeddings, allow_dangerous_deserialization=True)
client = OpenAI(api_key = OPENAI_API_KEY)
def find_or_create_customer_file(customer_name):
"""Finds the specified customer's file in the customer_files directory, or creates one if it doesn't exist."""
directory = "./customer_files"
customer_file = f"{customer_name}.txt"
file_path = os.path.join(directory, customer_file)
if not os.path.exists(file_path):
os.makedirs(directory, exist_ok=True)
with open(file_path, "w") as file:
# print(f"Customer file created: {file_path}")
file.write(f"Customer file created for {customer_name} on {datetime.now().isoformat()}\n")
return f"Customer file created for {customer_name} on {datetime.now().isoformat()}\n"
else:
with open(file_path, 'r') as file:
return file.read()
def update_customer_file(customer_name, query, response, username='default_user'):
"""Updates the specified customer's file with new data."""
file_path = f"./customer_files/{customer_name}.txt"
os.makedirs(os.path.dirname(file_path), exist_ok=True)
new_data_str = (
f"Customer Name: {customer_name}\n"
f"Query: {query}\n"
f"Response: {response}\n"
f"Timestamp: {datetime.now().isoformat()}\n"
f"Username: {username}\n"
"--------------------------\n"
)
with open(file_path, "a") as file:
file.write(new_data_str)
print(f"Data successfully appended to {file_path}.")
def extract_customer_name_ner(user_query):
if not user_query:
return "default_customer"
doc = nlp(user_query)
matcher = Matcher(nlp.vocab)
# Domain name pattern: Looks for sequences resembling domain names
pattern = [{"LIKE_URL": True}]
matcher.add("DOMAIN_NAME", [pattern])
matches = matcher(doc)
if matches:
_, start, end = max(matches, key=lambda x: x[2] - x[1]) # Select the longest match
return doc[start:end].text
# Fall back to spaCy NER
for ent in doc.ents:
if ent.label_ == 'ORG':
return ent.text
return 'default_customer'
def chatInterface():
st.title("Chat with OpenAI GPT-4")
# st_lottie(load_lottiefile("images/welcome.json"), speed=1, reverse=False, loop=True, quality="high", height=100)
if "conversation_state" not in st.session_state:
st.session_state["conversation_state"] = []
# Initialize chat history in session state
if "messages" not in st.session_state:
st.session_state.messages = []
for message in st.session_state.messages:
image = USER_AVATAR if message["role"] == "user" else BOT_AVATAR
with st.chat_message(message["role"], avatar=image):
st.markdown(message["content"])
if prompt := st.chat_input("User input"):
st.chat_message("user", avatar=USER_AVATAR).markdown(prompt)
customer_name = extract_customer_name_ner(prompt)
# print(customer_name)
system_prompt = f'''You are an AI assistant with access to various documents related to customer interactions and value creation strategies.\nThe user's organization name is '{customer_name}'.\n
Instructions:\n
1. Compare and analyze the user query within the context of Account Planning & Value Creation.\n
2. Use the information in the library for identifying personas, discovery questions, technical use cases, and provide a list of next steps under the 'System Generated' section.\n
3. Use sales information from Account Planning & Value Creation to compare, analyze, and identify gaps using the sales qualification methodology such as MEDDICC. Advise the information missing for each letter in MEDDICC and provide a list of next steps under the 'Sales Process' section.\n
4. Include a score for each sales process stage using scoring from Value Creation.\n
5. Provide clear and actionable next steps in two categories:\n
- System Generated\n
- Sales Process\n
- MEDDICC score
6. Use only the provided context and your knowledge base. Do not generate responses from prior unrelated knowledge.\n'''
context_retrieval_prompt = f'''You are an AI assistant with access to various documents related to customer interactions and value creation strategies.\nThe user's organization name is '{customer_name}'.\n
Instructions:\n
1. Compare and analyze the user query within the context of Account Planning & Value Creation.\n
2. Use the information in the library for identifying personas, discovery questions, technical use cases, and provide a list of next steps under the 'System Generated' section.\n
3. Use sales information from Account Planning & Value Creation to compare, analyze, and identify gaps using the sales qualification methodology such as MEDDICC. Advise the information missing for each letter in MEDDICC and provide a list of next steps under the 'Sales Process' section.\n
4. Include a score for each sales process stage using scoring from Value Creation.\n
5. Provide clear and actionable next steps in two categories:\n
- System Generated\n
- Sales Process\n
6. Generate a overall MEDDICC score
7. Use only the provided context and your knowledge base. Do not generate responses from prior unrelated knowledge.\n
User Question: {prompt}
'''
unique_docs = retriever_from_llm.invoke(context_retrieval_prompt)
retrieved_context = ''
for doc in unique_docs:
retrieved_context +=f"Doc content: {str(doc.page_content)}\nSource: {str(doc.metadata['source'])}"
user_prompt = prompt + "Context:\n"+ retrieved_context
st.session_state.messages.append({"role": "user", "content": user_prompt})
conversation_context = st.session_state["conversation_state"]
conversation_context.append({"role": "user", "content": user_prompt})
# Define an empty context variable
context = []
# Add system prompt to context if desired
context.append({"role": "system", "content": system_prompt})
# Add conversation context to context
context.extend(st.session_state["conversation_state"])
# Generate response from ChatGPT API
response = client.chat.completions.create(
model="gpt-4-0125-preview",
temperature=0,
messages=context,
stream=True
)
with st.chat_message("assistant", avatar=BOT_AVATAR):
# st.markdown(assistant_response)
result = ""
res_box = st.empty()
for chunk in response:
if chunk.choices[0].delta.content:
new_content = chunk.choices[0].delta.content
result += new_content # Add a space to separate words
res_box.markdown(f'{result}')
# print(result)
assistant_response = result
st.session_state.messages.append({"role": "assistant", "content": assistant_response})
conversation_context.append({"role": "assistant", "content": assistant_response})
update_customer_file(customer_name, prompt, assistant_response)
if __name__ == "__main__":
chatInterface()