Spaces:
Runtime error
Runtime error
refactor(app.py): remove unused imports and variables
Browse filesfeat(app.py): add support for persisting vector store to disk and increase number of retrieved documents to 3
feat(app.py): add functionality to reduce number of retrieved documents to 1 if the maximum number of tokens is exceeded
feat(app.py): add verbose mode to retrieval chain to aid debugging
feat(app.py): update chatbot to use the new RetrievalQA chain and add support for displaying source documents in the response
app.py
CHANGED
@@ -1,52 +1,23 @@
|
|
1 |
-
from langchain.chat_models import ChatOpenAI
|
2 |
-
from langchain.document_loaders import PyPDFLoader
|
3 |
-
from langchain.embeddings.openai import OpenAIEmbeddings
|
4 |
-
from langchain.embeddings.cohere import CohereEmbeddings
|
5 |
-
from langchain.text_splitter import CharacterTextSplitter
|
6 |
-
from langchain.vectorstores.elastic_vector_search import ElasticVectorSearch
|
7 |
-
from langchain.vectorstores import Chroma
|
8 |
-
from PyPDF2 import PdfWriter
|
9 |
import gradio as gr
|
10 |
-
import
|
11 |
-
from dotenv import load_dotenv
|
12 |
-
import openai
|
13 |
-
|
14 |
-
load_dotenv()
|
15 |
-
#비밀키 가져오기 시도중
|
16 |
-
# api_key = os.getenv('OPENAI_API_KEY') ## .env 파일 업로드하면 숨겨지지 않음 안됨
|
17 |
-
# api_key = os.environ['my_secret'] ## 안불러와짐
|
18 |
-
# api_key = os.getenv('my_secret') ## 3트 .env 대신 secret키를 불러오는 형태로 도전
|
19 |
-
os.environ["OPENAI_API_KEY"] = os.environ['my_secret']
|
20 |
-
|
21 |
-
loader = PyPDFLoader("/home/user/app/docs.pdf")
|
22 |
-
documents = loader.load()
|
23 |
-
|
24 |
-
text_splitter = CharacterTextSplitter(chunk_size=800, chunk_overlap=0)
|
25 |
-
texts = text_splitter.split_documents(documents)
|
26 |
-
|
27 |
-
#vector embedding
|
28 |
-
embeddings = OpenAIEmbeddings()
|
29 |
-
vector_store = Chroma.from_documents(texts, embeddings)
|
30 |
-
retriever = vector_store.as_retriever(search_kwargs={"k": 2})
|
31 |
-
|
32 |
from langchain.chat_models import ChatOpenAI
|
33 |
-
from langchain.
|
34 |
-
|
35 |
-
llm = ChatOpenAI(model_name="gpt-4", temperature=0) # Modify model_name if you have access to GPT-4
|
36 |
-
|
37 |
-
chain = RetrievalQAWithSourcesChain.from_chain_type(
|
38 |
-
llm=llm,
|
39 |
-
chain_type="stuff",
|
40 |
-
retriever = retriever,
|
41 |
-
return_source_documents=True)
|
42 |
-
|
43 |
from langchain.prompts.chat import (
|
44 |
ChatPromptTemplate,
|
45 |
-
SystemMessagePromptTemplate,
|
46 |
HumanMessagePromptTemplate,
|
|
|
47 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
|
49 |
-
|
|
|
|
|
50 |
Given the following summaries of a long document and a question, create a final answer with references ("SOURCES"), use "SOURCES" in capital letters regardless of the number of sources.
|
51 |
If you don't know the answer, just say that "I don't know", don't try to make up an answer.
|
52 |
----------------
|
@@ -56,55 +27,62 @@ You MUST answer in Korean and in Markdown format:"""
|
|
56 |
|
57 |
messages = [
|
58 |
SystemMessagePromptTemplate.from_template(system_template),
|
59 |
-
HumanMessagePromptTemplate.from_template("{question}")
|
60 |
]
|
61 |
|
62 |
prompt = ChatPromptTemplate.from_messages(messages)
|
63 |
|
64 |
-
from langchain.chat_models import ChatOpenAI
|
65 |
-
from langchain.chains import RetrievalQAWithSourcesChain
|
66 |
-
|
67 |
chain_type_kwargs = {"prompt": prompt}
|
68 |
|
69 |
-
|
70 |
-
|
71 |
-
chain = RetrievalQAWithSourcesChain.from_chain_type(
|
72 |
llm=llm,
|
73 |
chain_type="stuff",
|
74 |
-
retriever
|
75 |
return_source_documents=True,
|
76 |
-
chain_type_kwargs=chain_type_kwargs
|
|
|
|
|
77 |
)
|
78 |
|
79 |
-
query = "행복한 인생이란?"
|
80 |
-
result = chain(query)
|
81 |
-
|
82 |
-
|
83 |
-
for doc in result['source_documents']:
|
84 |
-
print('내용 : ' + doc.page_content[0:100].replace('\n', ' '))
|
85 |
-
print('파일 : ' + doc.metadata['source'])
|
86 |
-
print('페이지 : ' + str(doc.metadata['page']))
|
87 |
-
|
88 |
-
|
89 |
-
def respond(message, chat_history): # 채팅봇의 응답을 처리하는 함수를 정의합니다.
|
90 |
|
|
|
|
|
91 |
result = chain(message)
|
92 |
|
93 |
-
bot_message = result[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
|
95 |
-
|
96 |
-
|
97 |
|
98 |
-
|
|
|
99 |
|
100 |
-
return "", chat_history # 수정된 채팅 기록을 ��환합니다.
|
101 |
|
102 |
-
|
|
|
103 |
gr.Markdown("# 안녕하세요. 세이노와 대화해보세요.")
|
104 |
chatbot = gr.Chatbot(label="채팅창") # '채팅창'이라는 레이블을 가진 채팅봇 컴포넌트를 생성합니다.
|
105 |
msg = gr.Textbox(label="입력") # '입력'이라는 레이블을 가진 텍스트박스를 생성합니다.
|
106 |
clear = gr.Button("초기화") # '초기화'라는 레이블을 가진 버튼을 생성합니다.
|
107 |
|
108 |
-
msg.submit(
|
109 |
-
|
110 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
+
from langchain.chains import RetrievalQA
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
from langchain.chat_models import ChatOpenAI
|
4 |
+
from langchain.embeddings.openai import OpenAIEmbeddings
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
from langchain.prompts.chat import (
|
6 |
ChatPromptTemplate,
|
|
|
7 |
HumanMessagePromptTemplate,
|
8 |
+
SystemMessagePromptTemplate,
|
9 |
)
|
10 |
+
from langchain.vectorstores import Chroma
|
11 |
+
|
12 |
+
from constants import persist_directory
|
13 |
+
|
14 |
+
embedding = OpenAIEmbeddings()
|
15 |
+
vector_store = Chroma(persist_directory=persist_directory, embedding_function=embedding)
|
16 |
+
retriever = vector_store.as_retriever(search_kwargs={"k": 3})
|
17 |
|
18 |
+
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
|
19 |
+
|
20 |
+
system_template = """Use the following pieces of context to answer the users question shortly.
|
21 |
Given the following summaries of a long document and a question, create a final answer with references ("SOURCES"), use "SOURCES" in capital letters regardless of the number of sources.
|
22 |
If you don't know the answer, just say that "I don't know", don't try to make up an answer.
|
23 |
----------------
|
|
|
27 |
|
28 |
messages = [
|
29 |
SystemMessagePromptTemplate.from_template(system_template),
|
30 |
+
HumanMessagePromptTemplate.from_template("{question}"),
|
31 |
]
|
32 |
|
33 |
prompt = ChatPromptTemplate.from_messages(messages)
|
34 |
|
|
|
|
|
|
|
35 |
chain_type_kwargs = {"prompt": prompt}
|
36 |
|
37 |
+
chain = RetrievalQA.from_chain_type(
|
|
|
|
|
38 |
llm=llm,
|
39 |
chain_type="stuff",
|
40 |
+
retriever=retriever,
|
41 |
return_source_documents=True,
|
42 |
+
chain_type_kwargs=chain_type_kwargs,
|
43 |
+
reduce_k_below_max_tokens=True,
|
44 |
+
verbose=True,
|
45 |
)
|
46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
+
# 채팅봇의 응답을 처리하는 함수를 정의합니다.
|
49 |
+
def respond(message, chat_history):
|
50 |
result = chain(message)
|
51 |
|
52 |
+
bot_message = result["answer"]
|
53 |
+
|
54 |
+
for i, doc in enumerate(result["source_documents"]):
|
55 |
+
bot_message += (
|
56 |
+
"["
|
57 |
+
+ str(i + 1)
|
58 |
+
+ "] "
|
59 |
+
+ doc.metadata["source"]
|
60 |
+
+ "("
|
61 |
+
+ str(doc.metadata["page"])
|
62 |
+
+ ") "
|
63 |
+
)
|
64 |
|
65 |
+
# 채팅 기록에 사용자의 메시지와 봇의 응답을 추가합니다.
|
66 |
+
chat_history.append((message, bot_message))
|
67 |
|
68 |
+
# 수정된 채팅 기록을 반환합니다.
|
69 |
+
return "", chat_history
|
70 |
|
|
|
71 |
|
72 |
+
# gr.Blocks()를 사용하여 인터페이스를 생성합니다.
|
73 |
+
with gr.Blocks(theme="gstaff/sketch") as demo:
|
74 |
gr.Markdown("# 안녕하세요. 세이노와 대화해보세요.")
|
75 |
chatbot = gr.Chatbot(label="채팅창") # '채팅창'이라는 레이블을 가진 채팅봇 컴포넌트를 생성합니다.
|
76 |
msg = gr.Textbox(label="입력") # '입력'이라는 레이블을 가진 텍스트박스를 생성합니다.
|
77 |
clear = gr.Button("초기화") # '초기화'라는 레이블을 가진 버튼을 생성합니다.
|
78 |
|
79 |
+
msg.submit(
|
80 |
+
respond, [msg, chatbot], [msg, chatbot]
|
81 |
+
) # 텍스트박스에 메시지를 입력하고 제출하면 respond 함수가 호출되도록 합니다.
|
82 |
+
clear.click(
|
83 |
+
lambda: None, None, chatbot, queue=False
|
84 |
+
) # '초기화' 버튼을 클릭하면 채팅 기록을 초기화합니다.
|
85 |
+
|
86 |
+
demo.launch(
|
87 |
+
debug=True
|
88 |
+
) # 인터페이스를 실행합니다. 실행하면 사용자는 '입력' 텍스트박스에 메시지를 작성하고 제출할 수 있으며, '초기화' 버튼을 통해 채팅 기록을 초기화 할 수 있습니다.
|