File size: 5,900 Bytes
a56a0d0
 
 
8b16906
 
 
 
a56a0d0
 
 
 
8b16906
0a9b238
 
 
8b16906
 
0a9b238
 
a56a0d0
82ce806
8b16906
82ce806
0a9b238
a56a0d0
0a9b238
 
a56a0d0
0a9b238
a56a0d0
0a9b238
a56a0d0
 
0a9b238
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a56a0d0
82ce806
 
a56a0d0
047ea71
1301e19
 
 
 
a56a0d0
1301e19
8b16906
a56a0d0
 
 
 
 
 
8b16906
 
1301e19
a56a0d0
 
1301e19
a56a0d0
 
8b16906
0a9b238
 
 
 
 
8b16906
 
 
 
a56a0d0
8b16906
a56a0d0
 
 
 
1301e19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8b16906
1301e19
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

import streamlit as st
import faiss
import langchain
from llama_index.callbacks import CallbackManager
from llama_index import  ServiceContext,VectorStoreIndex
from llama_index.chat_engine import CondenseQuestionChatEngine
from llama_index.node_parser import SimpleNodeParser
from llama_index.langchain_helpers.text_splitter import TokenTextSplitter
from llama_index.constants import DEFAULT_CHUNK_OVERLAP
from llama_index.response_synthesizers import get_response_synthesizer
from llama_index import  SimpleWebPageReader
from llama_index.llms.base import ChatMessage, MessageRole
from llama_index.prompts.base import ChatPromptTemplate
from llama_index.prompts.base import  PromptTemplate
# from llama_index.prompts import Prompt
from llama_index import Prompt

from log import logger
import tiktoken
import common
langchain.verbose = True

custom_prompt = PromptTemplate("""\
  以下はこれまでの会話履歴と、ドキュメントを検索して回答する必要がある、ユーザーからの会話文です。
  会話と新しい会話文に基づいて、検索クエリを作成します。
  <Chat History> 
  {chat_history}
  <Follow Up Message>
  {question}
  <Standalone question>
""")

TEXT_QA_SYSTEM_PROMPT = ChatMessage(
    content=(
        "あなたは世界中で信頼されているQAシステムです。\n"
        "事前知識ではなく、常に提供されたコンテキスト情報を使用してクエリに回答してください。\n"
        "従うべきいくつかのルール:\n"
        "1. 回答内で指定されたコンテキストを直接参照しないでください。\n"
        "2. 「コンテキストに基づいて、...」や「コンテキスト情報は...」、またはそれに類するような記述は避けてください。"
    ),
    role=MessageRole.SYSTEM,
)

# QAプロンプトテンプレートメッセージ
TEXT_QA_PROMPT_TMPL_MSGS = [
    TEXT_QA_SYSTEM_PROMPT,
    ChatMessage(
        content=(
            "コンテキスト情報は以下のとおりです。\n"
            "---------------------\n"
            "{context_str}\n"
            "---------------------\n"
            "事前知識ではなくコンテキスト情報を考慮して、クエリに答えます。\n"
            "Query: {query_str}\n"
            "Answer: "
        ),
        role=MessageRole.USER,
    ),
]
CHAT_TEXT_QA_PROMPT = ChatPromptTemplate(message_templates=TEXT_QA_PROMPT_TMPL_MSGS)

CHAT_REFINE_PROMPT_TMPL_MSGS = [
    ChatMessage(
        content=(
            "あなたは、既存の回答を改良する際に2つのモードで厳密に動作するQAシステムのエキスパートです。\n"
            "1. 新しいコンテキストを使用して元の回答を**書き直す**。\n"
            "2. 新しいコンテキストが役に立たない場合は、元の回答を**繰り返す**。\n"
            "回答内で元の回答やコンテキストを直接参照しないでください。\n"
            "疑問がある場合は、元の答えを繰り返してください。"
            "New Context: {context_msg}\n"
            "Query: {query_str}\n"
            "Original Answer: {existing_answer}\n"
            "New Answer: "
        ),
        role=MessageRole.USER,
    )
]
# チャットRefineプロンプト
CHAT_REFINE_PROMPT = ChatPromptTemplate(message_templates=CHAT_REFINE_PROMPT_TMPL_MSGS)

common.check_login()

st.title("💬 ChatbotWebRead")

URLtext = st.text_input(
    "読み込むURLを入力してください",
    placeholder="https://",
)

if st.button("URL reading",use_container_width=True):
    text_splitter = TokenTextSplitter( chunk_size=1500
      , chunk_overlap=DEFAULT_CHUNK_OVERLAP
      , tokenizer=tiktoken.encoding_for_model("gpt-3.5-turbo").encode)
    node_parser = SimpleNodeParser(text_splitter=text_splitter)
    d = 1536
    k=2
    faiss_index = faiss.IndexFlatL2(d)

    callback_manager = CallbackManager([st.session_state.llama_debug_handler])
    service_context = ServiceContext.from_defaults(node_parser=node_parser,callback_manager=callback_manager)

    webDocuments = SimpleWebPageReader(html_to_text=True).load_data(
        [URLtext]
    )
    logger.info(webDocuments)
    webIndex = VectorStoreIndex.from_documents(webDocuments,service_context=service_context)
    response_synthesizer = get_response_synthesizer(
        response_mode='refine',
        text_qa_template= CHAT_TEXT_QA_PROMPT,
        refine_template=CHAT_REFINE_PROMPT,
    )
    st.session_state.webQuery_engine = webIndex.as_query_engine(
        response_synthesizer=response_synthesizer,
        service_context=service_context,
    )
    st.session_state.web_chat_engine = CondenseQuestionChatEngine.from_defaults(
        query_engine=st.session_state.webQuery_engine, 
        condense_question_prompt=custom_prompt,
        verbose=True
    )

if st.button("リセット",use_container_width=True,disabled = not URLtext):
    st.session_state.web_chat_engine.reset()
    st.session_state.webmessages = [{"role": "assistant", "content": "お困りごとはございますか?"}]
    st.experimental_rerun()
    logger.info("reset")

if "webmessages" not in st.session_state:
    st.session_state["webmessages"] = [{"role": "assistant", "content": "お困りごとはございますか?"}]

for msg in st.session_state.webmessages:
    st.chat_message(msg["role"]).write(msg["content"])

if prompt := st.chat_input(disabled = not URLtext):
    st.session_state.webmessages.append({"role": "user", "content": prompt})
    st.chat_message("user").write(prompt)
    response = st.session_state.web_chat_engine.chat(prompt)
    logger.debug(st.session_state.llama_debug_handler.get_llm_inputs_outputs())
    msg = str(response)
    st.session_state.webmessages.append({"role": "assistant", "content": msg})
    st.chat_message("assistant").write(msg)