|
import os |
|
import spacy |
|
|
|
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 |
|
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_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()) |
|
|
|
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 |
|
) |
|
|
|
|
|
|
|
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: |
|
|
|
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) |
|
|
|
|
|
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]) |
|
return doc[start:end].text |
|
|
|
|
|
for ent in doc.ents: |
|
if ent.label_ == 'ORG': |
|
return ent.text |
|
|
|
return 'default_customer' |
|
|
|
def chatInterface(): |
|
st.title("Chat with OpenAI GPT-4") |
|
|
|
|
|
if "conversation_state" not in st.session_state: |
|
st.session_state["conversation_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) |
|
|
|
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}) |
|
|
|
|
|
context = [] |
|
|
|
context.append({"role": "system", "content": system_prompt}) |
|
|
|
context.extend(st.session_state["conversation_state"]) |
|
|
|
|
|
response = client.chat.completions.create( |
|
model="gpt-4-0125-preview", |
|
temperature=0, |
|
messages=context, |
|
stream=True |
|
) |
|
|
|
with st.chat_message("assistant", avatar=BOT_AVATAR): |
|
|
|
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 |
|
res_box.markdown(f'{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() |