LoL_Lore / app.py
Cachoups's picture
Update app.py
aecb436 verified
raw
history blame
6.46 kB
import gradio as gr
from huggingface_hub import InferenceClient
from huggingface_hub import login
import re
import pandas as pd
from langchain.schema import Document
from langchain.text_splitter import TokenTextSplitter
from transformers import AutoTokenizer
import copy
from langchain_community.retrievers import BM25Retriever
"""
For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
"""
client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
df1 = pd.read_csv("./data/champions_data_lol.csv")
df1['Story'] = df1['Story'].astype(str)
# Pre-processing
def preprocess_for_bm25(text):
# Replace "..." with a unique placeholder
text = text.replace("...", " _ELLIPSIS_ ")
# Add space before and after punctuation (except "_ELLIPSIS_")
text = re.sub(r'([.,!?()"])', r' \1 ', text)
# Restore "..." from the placeholder
text = text.replace("_ELLIPSIS_", "...")
# Normalize spaces
text = re.sub(r'\s+', ' ', text).strip()
text = text.lower()
return text
"""Pre-processing"""
# Convert DataFrame to documents
documents = []
for _, row in df1.iterrows():
biography_text = row['Story']
documents.append(Document(
page_content= biography_text, # Text of the chunk
metadata= {
'champion_name': row['Champion'],
'role': row['Role']}
))
"""Chunking"""
# Specify the model name
EMBEDDING_MODEL_NAME = "HuggingFaceH4/zephyr-7b-beta"
tokenizer_name = EMBEDDING_MODEL_NAME
# Token splitting for more context split
text_splitter = TokenTextSplitter.from_huggingface_tokenizer(
tokenizer=AutoTokenizer.from_pretrained(tokenizer_name),
chunk_size=300,
chunk_overlap=30
)
chunks = text_splitter.split_documents(documents) # chunks used for LLM generation
chunks_bm25 = copy.deepcopy(chunks) # Creates an independent copy, chunks used for BM25 retriever
for i, doc in enumerate(chunks_bm25):
doc.page_content = preprocess_for_bm25(doc.page_content) # Modify page_content in place
doc.metadata["index"] = i # Add an index for tracking
for i, doc in enumerate(chunks):
doc.metadata["index"] = i # Add an index for tracking
"""Retriever"""
bm25_retriever = BM25Retriever.from_documents(chunks_bm25, k = 2) # 2 most similar contexts
"""Chain"""
from langchain_core.runnables.passthrough import RunnablePassthrough
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers.string import StrOutputParser
from langchain_community.llms.huggingface_hub import HuggingFaceHub
import os
from langchain_core.runnables import RunnableLambda
prompt = f"""
You are an expert in League of Legends (LoL) lore. You will only answer questions related to the champions and their stories within the game.
Instructions:
1. **Only use the context provided below** to answer the question. You should reference the context directly to ensure your answer is as relevant as possible.
2. If the question is outside the scope of League of Legends lore, respond by saying: *"Please ask something related to League of Legends lore."*
3. If the provided context does not provide a clear answer or you're unsure, respond by saying: *"I'm unsure based on the provided context."*
Context: {context}
Question: {question}
Answer:
"""
prompt_template = ChatPromptTemplate.from_template(prompt)
llm = HuggingFaceHub(
repo_id="HuggingFaceH4/zephyr-7b-beta",
model_kwargs={"temperature": 0.1, "max_length": 50, "return_full_text" : False}
)
def ra(user_question):
prompt = f"You know things about League of Legends. Please correct the following question for grammar and clarity.Do not give explaination:\n{user_question}\nCorrected question:"
# Pass the prompt to the LLM and get the response
rephrased_query = llm(prompt) # Replace `llm` with the appropriate LLM function or API call
new_query = rephrased_query.strip()
return {'context' : retriever(new_query), 'question': new_query}
# chain = RunnablePassthrough() | RunnableLambda(ra) | prompt_template | client.chat_completion() | StrOutputParser() for notebook
"""-------------------------------------------------------------------"""
def respond(
message,
history: list[tuple[str, str]],
system_message,
max_tokens,
temperature,
top_p,
):
res = ra(val[1])
system_message = f"""
You are an expert in League of Legends (LoL) lore. You will only answer questions related to the champions and their stories within the game.
Instructions:
1. **Only use the context provided below** to answer the question. You should reference the context directly to ensure your answer is as relevant as possible.
2. If the question is outside the scope of League of Legends lore, respond by saying: *"Please ask something related to League of Legends lore."*
3. If the provided context does not provide a clear answer or you're unsure, respond by saying: *"I'm unsure based on the provided context."*
Context: {res['context']}
Question: {res['question']}
Answer:
"""
messages = [{"role": "system", "content": system_message}]
for val in history:
if val[0]:
messages.append({"role": "user", "content": val[0]})
if val[1]:
messages.append({"role": "assistant", "content": val[1]})
messages.append({"role": "user", "content": message})
response = ""
for message in client.chat_completion(
messages,
max_tokens=max_tokens,
stream=True,
temperature=temperature,
top_p=top_p,
):
token = message.choices[0].delta.content
response += token
yield response
"""
For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
"""
demo = gr.ChatInterface(
respond,
additional_inputs=[
gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
gr.Slider(
minimum=0.1,
maximum=1.0,
value=0.95,
step=0.05,
label="Top-p (nucleus sampling)",
),
],
)
if __name__ == "__main__":
demo.launch()