Spaces:
Running
Running
import glob | |
import gradio as gr | |
import openai | |
import os | |
from dotenv import load_dotenv | |
import phoenix as px | |
import llama_index | |
from llama_index import Prompt, ServiceContext, VectorStoreIndex, SimpleDirectoryReader | |
from llama_index.chat_engine.types import ChatMode | |
from llama_index.llms import ChatMessage, MessageRole | |
from llama_index.vector_stores.qdrant import QdrantVectorStore | |
from llama_index.text_splitter import SentenceSplitter | |
from llama_index.extractors import TitleExtractor | |
from llama_index.ingestion import IngestionPipeline | |
from chat_template import CHAT_TEXT_QA_PROMPT, TEXT_QA_SYSTEM_PROMPT | |
from schemas import ChatbotVersion, ServiceProvider | |
from chatbot import Chatbot, IndexBuilder | |
from custom_io import MarkdownReader, UnstructuredReader, default_file_metadata_func | |
from qdrant import client as qdrantClient | |
from llama_index import set_global_service_context | |
from service_provider_config import get_service_provider_config | |
load_dotenv() | |
# initial service setup | |
px.launch_app() | |
llama_index.set_global_handler("arize_phoenix") | |
# llama_index.set_global_handler("wandb", run_args={"project": "llamaindex"}) | |
openai.api_key = os.getenv("OPENAI_API_KEY") | |
IS_LOAD_FROM_VECTOR_STORE = True | |
VDB_COLLECTION_NAME = "demo-v2" | |
MODEL_NAME = ChatbotVersion.CHATGPT_4.value | |
CHUNK_SIZE = 8191 | |
LLM, EMBED_MODEL = get_service_provider_config( | |
service_provider=ServiceProvider.OPENAI, model_name=MODEL_NAME) | |
service_context = ServiceContext.from_defaults( | |
chunk_size=CHUNK_SIZE, | |
llm=LLM, | |
embed_model=EMBED_MODEL, | |
) | |
set_global_service_context(service_context) | |
class AwesumIndexBuilder(IndexBuilder): | |
def _load_doucments(self): | |
directory = "./awesumcare_data/awesumcare_manual_data" | |
# all_files = glob.glob(os.path.join(directory, '*.md')) | |
# faq_files = [f for f in all_files if 'FAQ' in os.path.basename(f)] | |
# print(faq_files) | |
dir_reader = SimpleDirectoryReader(directory, file_extractor={ | |
".pdf": UnstructuredReader(), | |
".docx": UnstructuredReader(), | |
".pptx": UnstructuredReader(), | |
".md": MarkdownReader() | |
}, | |
recursive=True, | |
# input_files=faq_files, | |
exclude=["*.png", "*.pptx", "*.docx", "*.pdf"], | |
file_metadata=default_file_metadata_func) | |
self.documents = dir_reader.load_data() | |
print(f"Loaded {len(self.documents)} docs") | |
def _setup_service_context(self): | |
super()._setup_service_context() | |
def _setup_vector_store(self): | |
self.vector_store = QdrantVectorStore( | |
client=qdrantClient, collection_name=self.vdb_collection_name) | |
super()._setup_vector_store() | |
def _setup_index(self): | |
super()._setup_index() | |
if self.is_load_from_vector_store: | |
self.index = VectorStoreIndex.from_vector_store(self.vector_store) | |
print("set up index from vector store") | |
return | |
pipeline = IngestionPipeline( | |
transformations=[ | |
# SentenceSplitter(), | |
self.embed_model, | |
], | |
vector_store=self.vector_store, | |
) | |
pipeline.run(documents=self.documents, show_progress=True) | |
self.index = VectorStoreIndex.from_vector_store(self.vector_store) | |
class AwesumCareToolChatbot(Chatbot): | |
DENIED_ANSWER_PROMPT = "" | |
SYSTEM_PROMPT = "" | |
CHAT_EXAMPLES = [ | |
"什麼是安心三寶?", | |
"點樣立平安紙?", | |
"甚麼是⾒證?", | |
"訂立每份⽂件需要多少錢以及付款⽅法?", | |
"通過安⼼三寶製作的⽂件有法律效⼒嗎?", | |
] | |
def _setup_observer(self): | |
pass | |
def _setup_index(self): | |
super()._setup_index() | |
# def _setup_index(self): | |
# self.index = VectorStoreIndex.from_documents( | |
# self.documents, | |
# service_context=self.service_context | |
# ) | |
# super()._setup_index() | |
def _setup_query_engine(self): | |
super()._setup_query_engine() | |
self.query_engine = self.index.as_query_engine( | |
text_qa_template=CHAT_TEXT_QA_PROMPT) | |
def _setup_tools(self): | |
from llama_index.tools.query_engine import QueryEngineTool | |
self.tools = QueryEngineTool.from_defaults( | |
query_engine=self.query_engine) | |
return super()._setup_tools() | |
def _setup_chat_engine(self): | |
# testing # | |
from llama_index.agent import OpenAIAgent | |
self.chat_engine = OpenAIAgent.from_tools( | |
tools=[self.tools], | |
llm=LLM, | |
similarity_top_k=1, | |
verbose=True | |
) | |
print("set up agent as chat engine") | |
# testing # | |
# self.chat_engine = self.index.as_chat_engine( | |
# chat_mode=ChatMode.BEST, | |
# similarity_top_k=5, | |
# text_qa_template=CHAT_TEXT_QA_PROMPT) | |
super()._setup_chat_engine() | |
class AweSumCareContextChatbot(AwesumCareToolChatbot): | |
def _setup_query_engine(self): | |
pass | |
def _setup_tools(self): | |
pass | |
def _setup_chat_engine(self): | |
self.chat_engine = self.index.as_chat_engine( | |
chat_mode=ChatMode.CONTEXT, | |
similarity_top_k=5, | |
system_prompt=TEXT_QA_SYSTEM_PROMPT.content, | |
text_qa_template=CHAT_TEXT_QA_PROMPT) | |
class AweSumCareSimpleChatbot(AwesumCareToolChatbot): | |
def _setup_query_engine(self): | |
pass | |
def _setup_tools(self): | |
pass | |
def _setup_chat_engine(self): | |
self.chat_engine = self.index.as_chat_engine( | |
chat_mode=ChatMode.SIMPLE) | |
model_name = MODEL_NAME | |
index_builder = AwesumIndexBuilder(vdb_collection_name=VDB_COLLECTION_NAME, | |
embed_model=EMBED_MODEL, | |
is_load_from_vector_store=IS_LOAD_FROM_VECTOR_STORE) | |
# gpt-3.5-turbo-1106, gpt-4-1106-preview | |
awesum_chatbot = AwesumCareToolChatbot(model_name=model_name, index_builder=index_builder) | |
awesum_chatbot_context = AweSumCareContextChatbot(model_name=model_name, index_builder=index_builder) | |
awesum_chatbot_simple = AweSumCareSimpleChatbot(model_name=model_name, index_builder=index_builder) | |
def service_setup(model_name): | |
CHUNK_SIZE = 1024 | |
LLM, EMBED_MODEL = get_service_provider_config( | |
service_provider=ServiceProvider.OPENAI, model_name=model_name) | |
service_context = ServiceContext.from_defaults( | |
chunk_size=CHUNK_SIZE, | |
llm=LLM, | |
embed_model=EMBED_MODEL, | |
) | |
set_global_service_context(service_context) | |
return LLM, EMBED_MODEL | |
def vote(data: gr.LikeData): | |
if data.liked: | |
gr.Info("You up-voted this response: " + data.value) | |
else: | |
gr.Info("You down-voted this response: " + data.value) | |
chatbot = gr.Chatbot() | |
with gr.Blocks() as demo: | |
gr.Markdown("# Awesum Care demo") | |
# with gr.Row(): | |
# model_selector = gr.Radio( | |
# value=ChatbotVersion.CHATGPT_35.value, | |
# choices=[ChatbotVersion.CHATGPT_35.value, ChatbotVersion.CHATGPT_4.value], | |
# label="Select Chatbot Model (To be implemented)" | |
# ) | |
with gr.Tab("With relevant context sent to system prompt"): | |
context_interface = gr.ChatInterface( | |
awesum_chatbot_context.stream_chat, | |
examples=awesum_chatbot.CHAT_EXAMPLES, | |
) | |
chatbot.like(vote, None, None) | |
with gr.Tab("With function calling as tool to retrieve"): | |
function_call_interface = gr.ChatInterface( | |
awesum_chatbot.stream_chat, | |
examples=awesum_chatbot.CHAT_EXAMPLES, | |
) | |
chatbot.like(vote, None, None) | |
with gr.Tab("Vanilla ChatGPT without modification"): | |
vanilla_interface = gr.ChatInterface( | |
awesum_chatbot_simple.stream_chat, | |
examples=awesum_chatbot.CHAT_EXAMPLES) | |
gr.Markdown("instructions:\n" | |
"\nUsing model gpt-4-preview-1106, the most advanced model now in the market.\n" | |
"\n(Note that it can be much slower than gpt-3.5, openai's api can be unstable sometimes.)\n" | |
"\nThree Tabs:\n" | |
"1. Relevant context: retreiving relevant documents and send to ChatGPT.\n" | |
"2. Give tools to chatgpt to retrieve context: the most advanced, slowest (>30s to use the tools, before answering).\n" | |
"3. Vanilla ChatGPT: self-explanatory.\n" | |
) | |
# @model_selector.change(inputs=[model_selector, chatbot], outputs=[context_interface, function_call_interface, vanilla_interface]) | |
# def switch_model(model_name, my_chatbot): | |
# print(model_name) | |
# print(my_chatbot.config()) | |
# LLM, EMBED_MODEL = service_setup(model_name) | |
# # global awesum_chatbot, awesum_chatbot_context, awesum_chatbot_simple | |
# # Logic to switch models - create new instances of the chatbots with the selected model | |
# index_builder = AwesumIndexBuilder(vdb_collection_name=VDB_COLLECTION_NAME, | |
# embed_model=EMBED_MODEL, | |
# is_load_from_vector_store=IS_LOAD_FROM_VECTOR_STORE) | |
# awesum_chatbot = AwesumCareToolChatbot(model_name=model_name, index_builder=index_builder, llm=LLM) | |
# awesum_chatbot_context = AweSumCareContextChatbot(model_name=model_name, index_builder=index_builder) | |
# awesum_chatbot_simple = AweSumCareSimpleChatbot(model_name=model_name, index_builder=index_builder) | |
# # return awesum_chatbot.stream_chat, awesum_chatbot_context.stream_chat, awesum_chatbot_simple.stream_chat | |
# new_context_interface = gr.ChatInterface( | |
# awesum_chatbot_context.stream_chat, | |
# ) | |
# new_function_call_interface = gr.ChatInterface( | |
# awesum_chatbot.stream_chat, | |
# ) | |
# new_vanilla_interface = gr.ChatInterface( | |
# awesum_chatbot_simple.stream_chat, | |
# ) | |
# return new_context_interface, new_function_call_interface, new_vanilla_interface | |
demo.queue() | |
demo.launch(share=False) | |