"""
Demonstrates how to use the `ChatInterface` to create a chatbot using
[LangChain Expression Language](https://python.langchain.com/docs/expression_language/) (LCEL)
with streaming and memory.
"""
from operator import itemgetter
import panel as pn
from transformers import AutoTokenizer
from huggingface_hub import hf_hub_download
from langchain.memory import ConversationTokenBufferMemory
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_community.llms.llamacpp import LlamaCpp
pn.extension()
TOKENIZER_REPO_ID = "HuggingFaceH4/zephyr-7b-beta"
REPO_ID = "TheBloke/zephyr-7B-beta-GGUF"
FILENAME = "zephyr-7b-beta.Q5_K_M.gguf"
SYSTEM_PROMPT = "Be a helpful chatbot."
PROMPT_TEMPLATE = """
<|system|>
{system_prompt}</s>
{chat_history}
<|user|>
{user_input}</s>
<|assistant|>
""".strip()
ROLE_MAPPING = {
"system": "system",
"human": "user",
"ai": "assistant",
}
def load_llm(repo_id: str = REPO_ID, filename: str = FILENAME, **kwargs):
model_path = hf_hub_download(repo_id=repo_id, filename=filename)
llm = LlamaCpp(model_path=model_path, **kwargs)
return llm
def callback(contents: str, user: str, instance: pn.chat.ChatInterface):
message = ""
inputs = {"user_input": contents}
for token in chain.stream(inputs):
message += token
yield message
memory.save_context(inputs, {"output": message})
def apply_chat_template_to_history(history):
conversation = [
{"role": ROLE_MAPPING[message.type], "content": message.content}
for message in history["chat_history"]
]
tokenizer = AutoTokenizer.from_pretrained(TOKENIZER_REPO_ID)
chat_history = tokenizer.apply_chat_template(conversation, tokenize=False)
return chat_history
model_path = hf_hub_download(repo_id=REPO_ID, filename=FILENAME)
llm = LlamaCpp(
model_path=model_path,
streaming=True,
n_gpu_layers=1,
temperature=0.75,
max_tokens=1024,
n_ctx=8192,
top_p=1,
)
memory = ConversationTokenBufferMemory(
return_messages=True,
llm=llm,
memory_key="chat_history",
max_token_limit=8192 - 1024,
)
prompt = PromptTemplate.from_template(
PROMPT_TEMPLATE, partial_variables={"system_prompt": SYSTEM_PROMPT}
)
output_parser = StrOutputParser()
chain = (
RunnablePassthrough.assign(
chat_history=RunnableLambda(memory.load_memory_variables)
| itemgetter("chat_history")
)
| RunnablePassthrough.assign(chat_history=apply_chat_template_to_history)
| prompt
| llm
| output_parser
)
chat_interface = pn.chat.ChatInterface(
pn.chat.ChatMessage(
"Offer a topic and Mistral will try to be funny!", user="System"
),
callback=callback,
callback_user="Mistral",
callback_exception="verbose",
)
chat_interface.servable()