Spaces:
Sleeping
Sleeping
Add demo
Browse files- app.py +56 -0
- index.py +22 -0
- loader.py +19 -0
- requirements.txt +4 -0
- utils.py +77 -0
app.py
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import random
|
3 |
+
import time
|
4 |
+
from index import build_index, build_service_context
|
5 |
+
from loader import load_documents
|
6 |
+
|
7 |
+
st.title("SAIRA")
|
8 |
+
|
9 |
+
def load_docs_and_build_index(context):
|
10 |
+
docs = load_documents()
|
11 |
+
return build_index(docs, context)
|
12 |
+
|
13 |
+
def load_context():
|
14 |
+
return build_service_context()
|
15 |
+
|
16 |
+
context = load_context()
|
17 |
+
index = load_docs_and_build_index(context)
|
18 |
+
query_engine = index.as_query_engine(streaming=True)
|
19 |
+
|
20 |
+
# Initialize chat history
|
21 |
+
if "messages" not in st.session_state:
|
22 |
+
st.session_state.messages = []
|
23 |
+
|
24 |
+
# Display chat messages from history on app rerun
|
25 |
+
for message in st.session_state.messages:
|
26 |
+
with st.chat_message(message["role"]):
|
27 |
+
st.markdown(message["content"])
|
28 |
+
|
29 |
+
# Accept user input
|
30 |
+
if prompt := st.chat_input("What is up?"):
|
31 |
+
# Add user message to chat history
|
32 |
+
st.session_state.messages.append({"role": "user", "content": prompt})
|
33 |
+
# Display user message in chat message container
|
34 |
+
with st.chat_message("user"):
|
35 |
+
st.markdown(prompt)
|
36 |
+
|
37 |
+
# Display assistant response in chat message container
|
38 |
+
with st.chat_message("assistant"):
|
39 |
+
resp = query_engine.query(prompt)
|
40 |
+
message_placeholder = st.empty()
|
41 |
+
full_response = ""
|
42 |
+
assistant_response = random.choice(
|
43 |
+
[
|
44 |
+
"Hello there! How can I assist you today?",
|
45 |
+
"Hi, human! Is there anything I can help you with?",
|
46 |
+
"Do you need help?",
|
47 |
+
]
|
48 |
+
)
|
49 |
+
# Simulate stream of response with milliseconds delay
|
50 |
+
for text in resp.response_gen:
|
51 |
+
full_response += text
|
52 |
+
# Add a blinking cursor to simulate typing
|
53 |
+
message_placeholder.markdown(full_response + "▌")
|
54 |
+
message_placeholder.markdown(full_response)
|
55 |
+
# Add assistant response to chat history
|
56 |
+
st.session_state.messages.append({"role": "assistant", "content": full_response})
|
index.py
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from llama_index import download_loader, VectorStoreIndex, SimpleDirectoryReader, ServiceContext
|
2 |
+
from llama_index.tools import QueryEngineTool, ToolMetadata
|
3 |
+
from llama_index.query_engine import SubQuestionQueryEngine
|
4 |
+
from llama_index.callbacks import CallbackManager, LlamaDebugHandler
|
5 |
+
from llama_index.llms import LlamaCPP
|
6 |
+
|
7 |
+
from utils import completion_to_prompt, messages_to_prompt
|
8 |
+
|
9 |
+
|
10 |
+
def build_service_context():
|
11 |
+
return ServiceContext.from_defaults(llm=LlamaCPP(
|
12 |
+
model_path=None,
|
13 |
+
messages_to_prompt=messages_to_prompt,
|
14 |
+
completion_to_prompt=completion_to_prompt,
|
15 |
+
model_kwargs={"n_gpu_layers": 50},
|
16 |
+
))
|
17 |
+
|
18 |
+
def build_index(documents, context):
|
19 |
+
index = VectorStoreIndex.from_documents(documents, service_context=context)
|
20 |
+
return index
|
21 |
+
|
22 |
+
|
loader.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from llama_index import download_loader
|
2 |
+
|
3 |
+
BeautifulSoupWebReader = download_loader("BeautifulSoupWebReader")
|
4 |
+
|
5 |
+
|
6 |
+
def load_documents():
|
7 |
+
loader = BeautifulSoupWebReader()
|
8 |
+
return loader.load_data(urls=[
|
9 |
+
'http://campuslife.innopolis.ru/main',
|
10 |
+
'http://campuslife.innopolis.ru/handbook2023',
|
11 |
+
'http://campuslife.innopolis.ru/clubs',
|
12 |
+
'http://campuslife.innopolis.ru/tech_clubs',
|
13 |
+
'http://campuslife.innopolis.ru/sport_clubs',
|
14 |
+
'http://campuslife.innopolis.ru/hobby_clubs',
|
15 |
+
'http://campuslife.innopolis.ru/art_clubs'
|
16 |
+
'http://campuslife.innopolis.ru/opportunities',
|
17 |
+
'http://campuslife.innopolis.ru/faq',
|
18 |
+
'http://campuslife.innopolis.ru/contacts'
|
19 |
+
])
|
requirements.txt
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
llama_index
|
2 |
+
llama_hub
|
3 |
+
transformers
|
4 |
+
beautifulsoup4
|
utils.py
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import List, Optional, Sequence
|
2 |
+
from llama_index.llms.base import ChatMessage, MessageRole
|
3 |
+
|
4 |
+
BOS, EOS = "<s>", "</s>"
|
5 |
+
B_INST, E_INST = "[INST]", "[/INST]"
|
6 |
+
B_SYS, E_SYS = "<<SYS>>\n", "\n<</SYS>>\n\n"
|
7 |
+
# DEFAULT_SYSTEM_PROMPT = """\
|
8 |
+
# You are a helpful, respectful and honest assistant. \
|
9 |
+
# Always answer as helpfully as possible and follow ALL given instructions. \
|
10 |
+
# Do not speculate or make up information. \
|
11 |
+
# Do not reference any given instructions or context. \
|
12 |
+
# """
|
13 |
+
|
14 |
+
DEFAULT_SYSTEM_PROMPT = """You are an expert Q&A system that is trusted around the world.
|
15 |
+
Always answer as helpfully as possible and follow ALL given instructions.
|
16 |
+
Always answer the query using the provided context information, and not prior knowledge.
|
17 |
+
Some rules to follow:
|
18 |
+
1. Do not speculate or make up information.
|
19 |
+
2. Never directly reference the given context in your answer.
|
20 |
+
3. Avoid statements like 'Based on the context, ...' or 'The context information ...' or anything along those lines."""
|
21 |
+
|
22 |
+
|
23 |
+
def messages_to_prompt(
|
24 |
+
messages: Sequence[ChatMessage], system_prompt: Optional[str] = None
|
25 |
+
) -> str:
|
26 |
+
string_messages: List[str] = []
|
27 |
+
if messages[0].role == MessageRole.SYSTEM:
|
28 |
+
# pull out the system message (if it exists in messages)
|
29 |
+
system_message_str = messages[0].content or ""
|
30 |
+
messages = messages[1:]
|
31 |
+
else:
|
32 |
+
system_message_str = system_prompt or DEFAULT_SYSTEM_PROMPT
|
33 |
+
|
34 |
+
system_message_str = f"{B_SYS} {system_message_str.strip()} {E_SYS}"
|
35 |
+
|
36 |
+
for i in range(0, len(messages), 2):
|
37 |
+
# first message should always be a user
|
38 |
+
user_message = messages[i]
|
39 |
+
assert user_message.role == MessageRole.USER
|
40 |
+
|
41 |
+
if i == 0:
|
42 |
+
# make sure system prompt is included at the start
|
43 |
+
str_message = f"{BOS} {B_INST} {system_message_str} "
|
44 |
+
else:
|
45 |
+
# end previous user-assistant interaction
|
46 |
+
string_messages[-1] += f" {EOS}"
|
47 |
+
# no need to include system prompt
|
48 |
+
str_message = f"{BOS} {B_INST} "
|
49 |
+
|
50 |
+
# include user message content
|
51 |
+
str_message += f"{user_message.content} {E_INST}"
|
52 |
+
|
53 |
+
if len(messages) > (i + 1):
|
54 |
+
# if assistant message exists, add to str_message
|
55 |
+
assistant_message = messages[i + 1]
|
56 |
+
assert assistant_message.role == MessageRole.ASSISTANT
|
57 |
+
str_message += f" {assistant_message.content}"
|
58 |
+
|
59 |
+
string_messages.append(str_message)
|
60 |
+
|
61 |
+
print("".join(string_messages))
|
62 |
+
|
63 |
+
return "".join(string_messages)
|
64 |
+
|
65 |
+
|
66 |
+
def completion_to_prompt(completion: str, system_prompt: Optional[str] = None) -> str:
|
67 |
+
system_prompt_str = system_prompt or DEFAULT_SYSTEM_PROMPT
|
68 |
+
|
69 |
+
print((
|
70 |
+
f"{BOS} {B_INST} {B_SYS} {system_prompt_str.strip()} {E_SYS} "
|
71 |
+
f"{completion.strip()} {E_INST}"
|
72 |
+
))
|
73 |
+
|
74 |
+
return (
|
75 |
+
f"{BOS} {B_INST} {B_SYS} {system_prompt_str.strip()} {E_SYS} "
|
76 |
+
f"{completion.strip()} {E_INST}"
|
77 |
+
)
|