Allow users to add LLM within the UI (#6)

* Rename AzureChatOpenAI to LCAzureChatOpenAI
* Provide vanilla ChatOpenAI and AzureChatOpenAI
* Remove the highest accuracy, lowest cost criteria

These criteria are unnecessary. The users, not pipeline creators, should choose
which LLM to use. Furthermore, it's cumbersome to input this information,
really degrades user experience.

* Remove the LLM selection in simple reasoning pipeline
* Provide a dedicated stream method to generate the output
* Return placeholder message to chat if the text is empty
This commit is contained in:
Duc Nguyen (john)
2024-04-06 11:53:17 +07:00
committed by GitHub
parent e187e23dd1
commit a203fc0f7c
35 changed files with 1339 additions and 169 deletions

View File

@@ -1,6 +1,7 @@
import gradio as gr
from ktem.app import BasePage
from ktem.db.models import User, engine
from ktem.llms.ui import LLMManagement
from sqlmodel import Session, select
from .user import UserManagement
@@ -16,6 +17,9 @@ class AdminPage(BasePage):
with gr.Tab("User Management", visible=False) as self.user_management_tab:
self.user_management = UserManagement(self._app)
with gr.Tab("LLM Management") as self.llm_management_tab:
self.llm_management = LLMManagement(self._app)
def on_subscribe_public_events(self):
if self._app.f_user_management:
self._app.subscribe_event(

View File

@@ -9,6 +9,8 @@ from ktem.db.models import Conversation, engine
from sqlmodel import Session, select
from theflow.settings import settings as flowsettings
from kotaemon.base import Document
from .chat_panel import ChatPanel
from .chat_suggestion import ChatSuggestion
from .common import STATE
@@ -189,6 +191,7 @@ class ChatPage(BasePage):
self.chat_control.conversation_rn,
self.chat_panel.chatbot,
self.info_panel,
self.chat_state,
]
+ self._indices_input,
show_progress="hidden",
@@ -220,6 +223,7 @@ class ChatPage(BasePage):
self.chat_control.conversation_rn,
self.chat_panel.chatbot,
self.info_panel,
self.chat_state,
]
+ self._indices_input,
show_progress="hidden",
@@ -392,7 +396,7 @@ class ChatPage(BasePage):
return pipeline, reasoning_state
async def chat_fn(self, conversation_id, chat_history, settings, state, *selecteds):
def chat_fn(self, conversation_id, chat_history, settings, state, *selecteds):
"""Chat function"""
chat_input = chat_history[-1][0]
chat_history = chat_history[:-1]
@@ -403,52 +407,43 @@ class ChatPage(BasePage):
pipeline, reasoning_state = self.create_pipeline(settings, state, *selecteds)
pipeline.set_output_queue(queue)
asyncio.create_task(pipeline(chat_input, conversation_id, chat_history))
text, refs = "", ""
len_ref = -1 # for logging purpose
msg_placeholder = getattr(
flowsettings, "KH_CHAT_MSG_PLACEHOLDER", "Thinking ..."
)
print(msg_placeholder)
while True:
try:
response = queue.get_nowait()
except Exception:
state[pipeline.get_info()["id"]] = reasoning_state["pipeline"]
yield chat_history + [
(chat_input, text or msg_placeholder)
], refs, state
yield chat_history + [(chat_input, text or msg_placeholder)], refs, state
len_ref = -1 # for logging purpose
for response in pipeline.stream(chat_input, conversation_id, chat_history):
if not isinstance(response, Document):
continue
if response is None:
queue.task_done()
print("Chat completed")
break
if response.channel is None:
continue
if "output" in response:
if response["output"] is None:
if response.channel == "chat":
if response.content is None:
text = ""
else:
text += response["output"]
text += response.content
if "evidence" in response:
if response["evidence"] is None:
if response.channel == "info":
if response.content is None:
refs = ""
else:
refs += response["evidence"]
refs += response.content
if len(refs) > len_ref:
print(f"Len refs: {len(refs)}")
len_ref = len(refs)
state[pipeline.get_info()["id"]] = reasoning_state["pipeline"]
yield chat_history + [(chat_input, text)], refs, state
state[pipeline.get_info()["id"]] = reasoning_state["pipeline"]
yield chat_history + [(chat_input, text or msg_placeholder)], refs, state
async def regen_fn(
self, conversation_id, chat_history, settings, state, *selecteds
):
def regen_fn(self, conversation_id, chat_history, settings, state, *selecteds):
"""Regen function"""
if not chat_history:
gr.Warning("Empty chat")
@@ -456,12 +451,11 @@ class ChatPage(BasePage):
return
state["app"]["regen"] = True
async for chat, refs, state in self.chat_fn(
for chat, refs, state in self.chat_fn(
conversation_id, chat_history, settings, state, *selecteds
):
new_state = deepcopy(state)
new_state["app"]["regen"] = False
yield chat, refs, new_state
else:
state["app"]["regen"] = False
yield chat_history, "", state
state["app"]["regen"] = False