File size: 4,577 Bytes
a57afaa
4f344f6
8283b81
 
4f344f6
8283b81
 
4f344f6
9f1b384
a57afaa
 
 
 
 
 
4f344f6
 
 
 
eb9834e
9f1b384
ecaee96
 
 
 
 
 
 
 
 
 
9f1b384
ecaee96
9f1b384
ecaee96
9f1b384
ecaee96
 
9f1b384
 
 
 
 
1f3bcd9
4f344f6
 
 
9f1b384
8283b81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9f1b384
eb9834e
9309a39
8283b81
 
9f1b384
 
 
8283b81
 
1f3bcd9
9f1b384
 
 
 
 
 
 
 
 
 
4f344f6
 
 
 
 
 
 
 
1f3bcd9
 
eb9834e
 
4f344f6
 
 
9f1b384
4f344f6
 
9f1b384
 
 
4f344f6
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import json
import os
import chainlit as cl
import pandas as pd
from langchain.schema.runnable.config import RunnableConfig
from langchain.text_splitter import CharacterTextSplitter
from langchain.tools.retriever import create_retriever_tool
from langchain_community.agent_toolkits import SQLDatabaseToolkit
from langchain_community.agent_toolkits.sql.base import create_sql_agent
from langchain_community.utilities import SQLDatabase
from langchain_community.vectorstores import FAISS
from langchain_core.prompts import (
    ChatPromptTemplate,
    MessagesPlaceholder,
)
from langchain_core.runnables import RunnableLambda
from langchain_openai.chat_models import ChatOpenAI
from langchain_openai.embeddings import OpenAIEmbeddings
from sqlalchemy import create_engine

system = """You are an agent designed to interact with a SQL database.
Given an input question, create a syntactically correct {dialect} query to run, then look at the results of the query and return the answer.
Unless the user specifies a specific number of examples they wish to obtain, always limit your query to at most {top_k} results.
You can order the results by a relevant column to return the most interesting examples in the database.
Never query for all the columns from a specific table, only ask for the relevant columns given the question.
You have access to tools for interacting with the database.
Only use the given tools. Only use the information returned by the tools to construct your final answer.
You MUST double check your query before executing it. If you get an error while executing a query, rewrite the query and try again.

DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.

If you are prompted for the specific TEXT of a review, use the search_reviews tool to find the relevant review(s).

You have access to the following tables: {table_names}

If the question does not seem related to the database, just return "I don't know" as the answer."""


def setup():
    lf = pd.read_csv("Main.csv")
    engine = create_engine("sqlite:///TrustWhole1.db")
    lf.to_sql("MainTable", engine, index=True, if_exists="replace")
    db = SQLDatabase(engine=engine)

    llm = ChatOpenAI(
        model="gpt-4-turbo-preview", temperature=0, api_key=os.getenv("OPENAI_API_KEY")
    )
    sql_toolkit = SQLDatabaseToolkit(db=db, llm=llm)

    texts_to_split = ""
    with open("combined_extracted.json", "r") as file:
        data = json.load(file)

    for item in data:
        texts_to_split += (
            item["companyName"]
            + "\n"
            + item["reviewTitle"]
            + "\n"
            + item["reviewDescription"]
            + "\n\n"
        )

    text_splitter = CharacterTextSplitter(
        separator="\n",
        chunk_size=2500,
        chunk_overlap=100,
    )
    texts = text_splitter.split_text(texts_to_split)
    embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
    vectorstore = FAISS.from_texts(texts, embeddings)
    retriever = vectorstore.as_retriever()

    tool_retiv = create_retriever_tool(
        retriever,
        name="search_reviews",
        description="Use this tool to search for and retrieve relevant reviews and their titles for the companies mentioned in the user's query. This tool should be used when the question cannot be directly answered using SQL, particularly when the query involves non-numeric information or requires contextual understanding from the reviews. However, if the question involves aggregation operations or primarily focuses on numerical data, the SQL tool should be used instead.",
    )

    prompt = ChatPromptTemplate.from_messages(
        [
            ("system", system),
            ("human", "{input}"),
            MessagesPlaceholder("agent_scratchpad"),
        ]
    )

    sql_agent = create_sql_agent(
        llm,
        toolkit=sql_toolkit,
        prompt=prompt,
        verbose=True,
        agent_type="openai-tools",
        extra_tools=[tool_retiv],
    )

    return sql_agent | RunnableLambda(lambda x: x["output"])


agent_executor = setup()


@cl.on_chat_start
async def on_chat_start():
    cl.user_session.set("agent_executor", agent_executor)


@cl.on_message
async def main(message):
    agent_executor = cl.user_session.get("agent_executor")

    msg = cl.Message(content="")
    stream = agent_executor.astream(
        {"input": message.content},
        config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler()]),
    )
    async for chunk in stream:
        await msg.stream_token(chunk)

    await msg.send()