|
import chainlit as cl |
|
import pandas as pd |
|
import io |
|
import matplotlib.pyplot as plt |
|
import base64 |
|
from io import BytesIO |
|
from pandasai import SmartDataframe |
|
import pandas as pd |
|
from pandasai.llm import OpenAI |
|
from io import StringIO |
|
import matplotlib.pyplot as plt |
|
import csv |
|
from collections import defaultdict |
|
import os |
|
|
|
|
|
from langchain.agents import AgentExecutor, AgentType, initialize_agent |
|
from langchain.agents.structured_chat.prompt import SUFFIX |
|
from langchain.chat_models import ChatOpenAI |
|
from langchain.memory import ConversationBufferMemory |
|
|
|
from chainlit.action import Action |
|
from chainlit.input_widget import Select, Switch, Slider |
|
|
|
from langchain.tools import StructuredTool, Tool |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
got_csv = False |
|
|
|
|
|
@cl.on_chat_start |
|
async def start(): |
|
""" |
|
This is called when the Chainlit chat is started! |
|
We can add some settings to our application to allow users to select the appropriate model, and more! |
|
""" |
|
settings = await cl.ChatSettings( |
|
[ |
|
Select( |
|
id="Model", |
|
label="OpenAI - Model", |
|
values=["gpt-3.5-turbo", "gpt-4-1106-preview"], |
|
initial_index=1, |
|
), |
|
Switch(id="Streaming", label="OpenAI - Stream Tokens", initial=True), |
|
Slider( |
|
id="Temperature", |
|
label="OpenAI - Temperature", |
|
initial=0, |
|
min=0, |
|
max=2, |
|
step=0.1, |
|
), |
|
] |
|
).send() |
|
await setup_agent(settings) |
|
|
|
|
|
@cl.on_settings_update |
|
async def setup_agent(settings): |
|
print("Setup agent with following settings: ", settings) |
|
|
|
|
|
llm = ChatOpenAI( |
|
temperature=settings["Temperature"], |
|
streaming=settings["Streaming"], |
|
model=settings["Model"], |
|
) |
|
|
|
|
|
memory = get_memory() |
|
|
|
|
|
_SUFFIX = "Chat history:\n{chat_history}\n\n" + SUFFIX |
|
|
|
|
|
|
|
agent = initialize_agent( |
|
llm=llm, |
|
tools = [ |
|
generate_most_valuable_feature |
|
], |
|
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION, |
|
memory=memory, |
|
agent_kwargs={ |
|
"suffix": _SUFFIX, |
|
"input_variables": ["input", "agent_scratchpad", "chat_history"], |
|
}, |
|
) |
|
cl.user_session.set("agent", agent) |
|
|
|
|
|
|
|
@cl.cache |
|
def get_memory(): |
|
""" |
|
This is used to track the conversation history and allow our agent to |
|
remember what was said before. |
|
""" |
|
return ConversationBufferMemory(memory_key="chat_history") |
|
|
|
|
|
def find_most_valuable_feature(csv_file): |
|
print("find_most_valuable_feature") |
|
print(csv_file) |
|
|
|
smart_llm = OpenAI(api_token=os.environ["OPENAI_API_KEY"]) |
|
|
|
|
|
|
|
|
|
|
|
columns = defaultdict(list) |
|
|
|
|
|
with open("upload.csv") as f: |
|
reader = csv.reader(f) |
|
headers = next(reader) |
|
|
|
for row in reader: |
|
for header, value in zip(headers, row): |
|
columns[header].append(value) |
|
|
|
|
|
smart_df = pd.DataFrame({ |
|
"ID": columns["ID"], |
|
"Date and Time": columns["Date and Time"], |
|
"Business Unit": columns["Business Unit"], |
|
"Usage Change": columns["Usage Change"], |
|
"Wolftech Improvement": columns["Wolftech Improvement"], |
|
"Likelihood to Recommend": columns["Likelihood to Recommend"], |
|
"Effective Training": columns["Effective Training"], |
|
"Most Valuable Feature": columns["Most Valuable Feature"] |
|
}) |
|
|
|
smart_df = SmartDataframe(smart_df, config={"llm": smart_llm}) |
|
out = smart_df.chat('Summarize the top three "Most Valuable Feature" for people where Usage Changed was Increased?') |
|
|
|
print(out) |
|
|
|
|
|
df = out |
|
|
|
|
|
plt.figure(figsize=(10, 6)) |
|
plt.bar(df["Most Valuable Feature"], df["Count"], color='blue') |
|
plt.xlabel('Most Valuable Feature') |
|
plt.ylabel('Count') |
|
plt.title('Count of Most Valuable Features') |
|
plt.xticks(rotation=45, ha="right") |
|
plt.tight_layout() |
|
|
|
|
|
image_buffer = BytesIO() |
|
plt.savefig(image_buffer, format='png') |
|
image_buffer.seek(0) |
|
|
|
return image_buffer |
|
|
|
|
|
generate_most_valuable_feature = Tool.from_function( |
|
func=find_most_valuable_feature, |
|
name="Find most valuable feature", |
|
description=f"Useful for finding the most valuable feature from a CSV file", |
|
return_direct=True, |
|
) |
|
|
|
|
|
|
|
def process_and_analyze_data(csv_file): |
|
|
|
csv_data = pd.read_csv(csv_file) |
|
|
|
|
|
print(f"CSV Data Loaded: {csv_data.head()}") |
|
|
|
|
|
business_unit_counts = csv_data['Business Unit'].value_counts() |
|
|
|
|
|
plt.figure(figsize=(10, 6)) |
|
business_unit_counts.plot(kind='bar') |
|
plt.title('Count of Responses by Business Unit') |
|
plt.xlabel('Business Unit') |
|
plt.ylabel('Count') |
|
plt.xticks(rotation=45) |
|
plt.tight_layout() |
|
|
|
|
|
image_buffer = BytesIO() |
|
plt.savefig(image_buffer, format='png') |
|
image_buffer.seek(0) |
|
|
|
return image_buffer |
|
|
|
|
|
|
|
|
|
@cl.on_message |
|
async def handle_message(message: cl.Message): |
|
global got_csv, agent |
|
|
|
csv_file = next( |
|
( |
|
io.BytesIO(file.content) |
|
for file in message.elements or [] |
|
if file.mime and "csv" in file.mime |
|
), |
|
None, |
|
) |
|
|
|
|
|
print(f"CSV File: {csv_file}") |
|
|
|
if csv_file: |
|
got_csv = True |
|
try: |
|
|
|
image_buffer = find_most_valuable_feature(csv_file) |
|
|
|
|
|
image_data = image_buffer.getvalue() |
|
name = "chart" |
|
cl.user_session.set(name, image_data) |
|
cl.user_session.set("generated_image", name) |
|
|
|
await cl.Message(content="Based on the people who increased usage, here are the most valuable features...").send() |
|
|
|
generated_image = cl.user_session.get(name) |
|
|
|
agent = cl.user_session.get("agent") |
|
|
|
res = await cl.make_async(agent.run)( |
|
input=message.content, callbacks=[cl.LangchainCallbackHandler()] |
|
) |
|
|
|
elements = [] |
|
actions = [] |
|
|
|
elements = [ |
|
cl.Image( |
|
content=generated_image, |
|
name=name, |
|
display="inline", |
|
size="large" |
|
) |
|
] |
|
|
|
await cl.Message(content=name, elements=elements, actions=actions).send() |
|
|
|
|
|
except Exception as e: |
|
await cl.Message(content=f"An error occurred: {str(e)}").send() |
|
else: |
|
if not got_csv: |
|
await cl.Message(content="Please upload a CSV file.").send() |
|
else: |
|
res = await cl.make_async(agent.run)( |
|
input=message.content, callbacks=[cl.LangchainCallbackHandler()] |
|
) |
|
await cl.Message(content=res).send() |
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
cl.run() |
|
|