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 from schemas import ChatbotVersion, ServiceProvider from chatbot import Chatbot, IndexBuilder from custom_io import 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-v0" MODEL_NAME = ChatbotVersion.CHATGPT_4.value 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) class AwesumIndexBuilder(IndexBuilder): def _load_doucments(self): dir_reader = SimpleDirectoryReader('./awesumcare_data', file_extractor={ ".pdf": UnstructuredReader(), ".docx": UnstructuredReader(), ".pptx": UnstructuredReader(), }, recursive=True, exclude=["*.png", "*.pptx"], 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, 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") 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" ) # 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) # @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)