yeelou commited on
Commit
f64b1f0
·
1 Parent(s): c29ddbb

add ans params

Browse files
.gitignore CHANGED
@@ -1,4 +1,5 @@
1
  __pycache__
2
  old
3
  .env
4
- resource/QA*
 
 
1
  __pycache__
2
  old
3
  .env
4
+ resource/QA*
5
+ resource.zip
.gradio/certificate.pem ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN CERTIFICATE-----
2
+ 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
31
+ -----END CERTIFICATE-----
app.py CHANGED
@@ -7,6 +7,7 @@ import time
7
  import gradio as gr
8
 
9
  from blog_class import audio_text, knowledge_class, save_feedback
 
10
 
11
  knowledge_cls = knowledge_class()
12
 
@@ -25,29 +26,44 @@ def user_message_fn(user_message, history):
25
  return "", history
26
 
27
 
28
- def answer_question(history):
29
  print("chat Start")
30
- answer_text, info_title, audio_file_path = knowledge_cls.get_chat_answer(history)
 
 
31
  if not answer_text:
32
  yield history
33
  return
 
 
 
 
34
  audio_answer_container = {"result": None}
35
 
36
  def run_audio_answer():
37
  audio_answer_container["result"] = audio_text(answer_text, audio_file_path)
38
 
39
- audio_thread = threading.Thread(target=run_audio_answer)
40
- audio_thread.start()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
- history.append({"role": "assistant", "content": ""})
43
  #
44
- history.append(
45
- {
46
- "role": "assistant",
47
- "content": "音声作成中...",
48
- "metadata": {"title": "🎧 音声返信", "status": "pending"},
49
- }
50
- )
51
 
52
  history.append(
53
  {
@@ -80,22 +96,25 @@ def answer_question(history):
80
 
81
  yield history
82
  time.sleep(0.03)
83
- while audio_thread.is_alive():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  yield history
85
- time.sleep(0.2)
86
- audio_thread.join()
87
- print("chat end")
88
- if history[-2]["metadata"]["status"] != "done":
89
- audio_str = base64.b64encode(open(audio_file_path, "rb").read()).decode("utf-8")
90
- history[-2]["content"] = gr.HTML(
91
- f"""
92
- <audio controls>
93
- <source src="data:audio/mp3;base64,{audio_str}" type="audio/mp3">
94
- </audio>
95
- """
96
- )
97
- history[-2]["metadata"] = {"title": "🎧 音声返信", "status": "done"}
98
- yield history
99
 
100
 
101
  def handle_feedback(like_data: gr.LikeData):
@@ -122,105 +141,52 @@ def zip_directory():
122
  return zip_path
123
 
124
 
125
- custom_css = """
126
- body {
127
- background-color: #eef2f7;
128
- margin: 0;
129
- padding: 0;
130
- font-family: "Microsoft YaHei", sans-serif;
131
- }
132
-
133
- #title-area {
134
- text-align: center;
135
- margin-top: 30px;
136
- margin-bottom: 15px;
137
- color: #333;
138
- }
139
-
140
- #chatbot-container, #references-container, #download-container {
141
- max-width: 1100px;
142
- margin: auto;
143
- background: #f0f7ff;
144
- }
145
-
146
- #chatbot-container {
147
- border-radius: 12px;
148
- box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
149
- padding: 10px;
150
- }
151
-
152
- #references-container {
153
- border-radius: 12px;
154
- box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
155
- padding: 15px;
156
- }
157
-
158
- #submit-btn button {
159
- background-color: #007bff;
160
- color: white;
161
- border-radius: 8px;
162
- padding: 8px 12px;
163
- }
164
-
165
- #update-btn button {
166
- background-color: #28a745;
167
- color: white;
168
- border-radius: 8px;
169
- padding: 8px 12px;
170
- }
171
-
172
- h3 {
173
- color: #444;
174
- border-bottom: 2px solid #eee;
175
- padding-bottom: 8px;
176
- margin-bottom: 20px;
177
- }
178
- """
179
- custom_head = """
180
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css">
181
- <script src="https://unpkg.com/@dotlottie/player-component@2.7.12/dist/dotlottie-player.mjs" type="module"></script>
182
- """
183
-
184
- js_func = """
185
- function refresh() {
186
- const url = new URL(window.location);
187
-
188
- if (url.searchParams.get('__theme') !== 'light') {
189
- url.searchParams.set('__theme', 'light');
190
- window.location.href = url.href;
191
- }
192
- }
193
- """
194
- with gr.Blocks(title="勉強会", css=custom_css, head=custom_head, js=js_func) as demo:
195
 
196
- with gr.Column(elem_id="title-area"):
197
- gr.HTML(
198
- """
199
- <div style="display: flex; align-items: center; justify-content: center;">
200
- <img src="https://cdn.profile-image.st-hatena.com/users/saratoga623/profile.png?1728512391" style="width:50px; height:50px; margin-right:10px;">
201
- <h1 style="margin: 0;">
202
- <a href="https://saratoga623.hatenablog.com/" target="_blank" style="text-decoration: none; color: inherit;">
203
- プロジェクトマネジメント勉強会 <i class='fa fa-lightbulb-o'></i>
204
- </a>
205
- </h1>
206
- </div>
207
- """
208
  )
209
- gr.HTML(
210
- """
211
- <div style="display: flex; align-items: center; justify-content: center;">
212
- <div>
213
- <p>経験上、プロジェクトマネジメントで大切だと思っている考え方で</p>
214
- <p>疑問に答え、音声、参考資料が提供されます</p>
215
- </div>
216
- <dotlottie-player src="https://lottie.host/e2d675e6-73f4-4e92-a217-89bf1a4e49d3/cyif3Z9bwS.lottie"
217
- background="transparent" speed="1" style="width: 150px; height: 150px" loop autoplay></dotlottie-player>
218
- </div>
219
- """
220
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
 
222
  with gr.Column(elem_id="chatbot-container"):
223
- gr.HTML("<h3><i class='fa fa-question-circle'></i> 何かお困りですか?</h3>")
 
 
 
 
224
  chatbot = gr.Chatbot(
225
  show_label=False,
226
  type="messages",
@@ -275,11 +241,19 @@ with gr.Blocks(title="勉強会", css=custom_css, head=custom_head, js=js_func)
275
 
276
  msg.submit(
277
  fn=user_message_fn, inputs=[msg, chatbot], outputs=[msg, chatbot], queue=False
278
- ).then(fn=answer_question, inputs=chatbot, outputs=chatbot)
 
 
 
 
279
 
280
  submit_btn.click(
281
  fn=user_message_fn, inputs=[msg, chatbot], outputs=[msg, chatbot], queue=False
282
- ).then(fn=answer_question, inputs=chatbot, outputs=chatbot)
 
 
 
 
283
  chatbot.like(handle_feedback, None, None, like_user_message=True)
284
  update_btn.click(
285
  fn=update_knowledge,
@@ -293,6 +267,9 @@ with gr.Blocks(title="勉強会", css=custom_css, head=custom_head, js=js_func)
293
  )
294
 
295
  download_btn.click(fn=zip_directory, outputs=file_output)
 
 
 
296
 
297
  # app
298
  if __name__ == "__main__":
 
7
  import gradio as gr
8
 
9
  from blog_class import audio_text, knowledge_class, save_feedback
10
+ from design import custom_css, custom_head, js_func, params_text, title_html, title_text
11
 
12
  knowledge_cls = knowledge_class()
13
 
 
26
  return "", history
27
 
28
 
29
+ def answer_question(history, creative_flag, full_flag, audio_flag):
30
  print("chat Start")
31
+ answer_text, info_title, audio_file_path = knowledge_cls.get_chat_answer(
32
+ history, creative_flag, full_flag
33
+ )
34
  if not answer_text:
35
  yield history
36
  return
37
+
38
+ # text
39
+ history.append({"role": "assistant", "content": ""})
40
+
41
  audio_answer_container = {"result": None}
42
 
43
  def run_audio_answer():
44
  audio_answer_container["result"] = audio_text(answer_text, audio_file_path)
45
 
46
+ if audio_flag:
47
+ audio_answer_container["result"] = "result"
48
+ history.append(
49
+ {
50
+ "role": "assistant",
51
+ "content": "音声なし",
52
+ "metadata": {"title": "🎧 音声返信", "status": "done"},
53
+ }
54
+ )
55
+ else:
56
+ audio_thread = threading.Thread(target=run_audio_answer)
57
+ audio_thread.start()
58
+ history.append(
59
+ {
60
+ "role": "assistant",
61
+ "content": "音声作成中...",
62
+ "metadata": {"title": "🎧 音声返信", "status": "pending"},
63
+ }
64
+ )
65
 
 
66
  #
 
 
 
 
 
 
 
67
 
68
  history.append(
69
  {
 
96
 
97
  yield history
98
  time.sleep(0.03)
99
+ if not audio_flag:
100
+ while audio_thread.is_alive():
101
+ yield history
102
+ time.sleep(0.2)
103
+ audio_thread.join()
104
+ print("chat end")
105
+ if history[-2]["metadata"]["status"] != "done":
106
+ audio_str = base64.b64encode(open(audio_file_path, "rb").read()).decode(
107
+ "utf-8"
108
+ )
109
+ history[-2]["content"] = gr.HTML(
110
+ f"""
111
+ <audio controls>
112
+ <source src="data:audio/mp3;base64,{audio_str}" type="audio/mp3">
113
+ </audio>
114
+ """
115
+ )
116
+ history[-2]["metadata"] = {"title": "🎧 音声返信", "status": "done"}
117
  yield history
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
 
120
  def handle_feedback(like_data: gr.LikeData):
 
141
  return zip_path
142
 
143
 
144
+ def toggle_change():
145
+ return None, None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
+
148
+ with gr.Blocks(title="勉強会", css=custom_css, head=custom_head, js=js_func) as demo:
149
+ with gr.Sidebar(label="回答スタイル調整", open=False):
150
+ with gr.Accordion("回答スタイルの違いについて", open=False):
151
+ gr.Markdown(params_text)
152
+
153
+ creativity_toggle = gr.Radio(
154
+ [("創造的な回答", True), ("事実的な回答", False)],
155
+ value=False,
156
+ label="回答スタイル",
 
 
157
  )
158
+ length_toggle = gr.Radio(
159
+ [("詳細な説明", True), ("簡潔な説明", False)],
160
+ value=False,
161
+ label="説明スタイル",
162
+ )
163
+ audio_toggle = gr.Radio(
164
+ [("テキスト", True), ("音声とテキスト", False)],
165
+ value=False,
166
+ label="返信スタイル",
 
 
167
  )
168
+ # creativity_toggle = Toggle(
169
+ # label="創意内容",
170
+ # value=False,
171
+ # interactive=True,
172
+ # color="#007bff",
173
+ # )
174
+ # length_toggle = Toggle(
175
+ # label="詳細内容",
176
+ # value=False,
177
+ # interactive=True,
178
+ # color="#007bff",
179
+ # )
180
+ with gr.Column(elem_id="title-area"):
181
+ gr.HTML(title_html)
182
+ gr.HTML(title_text)
183
 
184
  with gr.Column(elem_id="chatbot-container"):
185
+
186
+ gr.HTML(
187
+ "<h3><i class='fa fa-question-circle'></i> 何かお困りですか?</h3>",
188
+ )
189
+
190
  chatbot = gr.Chatbot(
191
  show_label=False,
192
  type="messages",
 
241
 
242
  msg.submit(
243
  fn=user_message_fn, inputs=[msg, chatbot], outputs=[msg, chatbot], queue=False
244
+ ).then(
245
+ fn=answer_question,
246
+ inputs=[chatbot, creativity_toggle, length_toggle, audio_toggle],
247
+ outputs=chatbot,
248
+ )
249
 
250
  submit_btn.click(
251
  fn=user_message_fn, inputs=[msg, chatbot], outputs=[msg, chatbot], queue=False
252
+ ).then(
253
+ fn=answer_question,
254
+ inputs=[chatbot, creativity_toggle, length_toggle, audio_toggle],
255
+ outputs=chatbot,
256
+ )
257
  chatbot.like(handle_feedback, None, None, like_user_message=True)
258
  update_btn.click(
259
  fn=update_knowledge,
 
267
  )
268
 
269
  download_btn.click(fn=zip_directory, outputs=file_output)
270
+ creativity_toggle.change(fn=toggle_change, inputs=None, outputs=[msg, chatbot])
271
+ length_toggle.change(fn=toggle_change, inputs=None, outputs=[msg, chatbot])
272
+ audio_toggle.change(fn=toggle_change, inputs=None, outputs=[msg, chatbot])
273
 
274
  # app
275
  if __name__ == "__main__":
blog_class.py CHANGED
@@ -13,6 +13,21 @@ from fish_audio_sdk import Session, TTSRequest
13
  from openai import OpenAI
14
  from tenacity import retry, stop_after_attempt, wait_exponential
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  try:
17
  from dotenv import load_dotenv
18
 
@@ -29,76 +44,7 @@ BASE_URL = "https://saratoga623.hatenablog.com/"
29
  client = OpenAI(api_key=os.getenv("gpt"))
30
 
31
  #
32
- audio_key = os.getenv("audio")
33
- if not audio_key:
34
- raise ValueError("环境变量 'audio' 未设置或为空")
35
- audio_client = Session(audio_key)
36
-
37
- SYS_Prompt = """
38
- あなたは言語の専門家であり、さまざまな話し方や思考パターンを分析し、模倣し、適応することに長けています。
39
- """
40
-
41
- SUMMARY_Prompt = """
42
- あなたは文章の内容を分析する専門家です。
43
- 以下の文章の要約を作成してください。要約は100字以内で簡潔にまとめてください。
44
- """
45
-
46
- STYLE_Prompt = """
47
- あなたは文章の内容を分析する専門家です。
48
- 以下の文章内容を分析して、
49
- 1. 原文の作者の文体を抽出してください。例:敬語、語気、構造、用語など代表的なもの
50
- 2. 原文の作者の思考パターンを抽出してください。例:論理構成、推論、態度など代表的なもの
51
- """
52
- SEGMENT_Prompt = """
53
- あなたは文章の内容を分析する専門家です。
54
- 以下の文章を内容に基づいて意味的に段落に分割してください。各段落は独立した文章で、段落ごとに改行を入れてください。
55
- """
56
-
57
- QA_Prompt = """
58
- ユーザーの質問に応じて表現を的確に調整し、自然でスムーズな対話を実現し、\
59
- 検索された情報の内容、文脈、コミュニケーションスタイルに適した応答を簡潔に提供してください。
60
-
61
- 【ユーザーの質問】
62
- {q_text}
63
- 【検索された情報】
64
- {r_text}
65
- 【タスク要求】
66
- - 検索された情報を参考に、質問に会話の形で回答すること。
67
- - 原文の作者の文体を模倣すること。
68
- - 原文の思考パターンを模倣すること。
69
- - 簡潔な回答を心がけること。3-5文程度で要点をまとめることを意識してください。
70
- - 文章風ではなく、対話形式で答えること。
71
- """
72
- REWRITE_SYS_Prompt = """
73
- Given a conversation (between Human and Assistant) and a follow up message from Human, \
74
- rewrite the message to be a standalone question that captures all relevant context \
75
- from the conversation.
76
- """
77
- REWRITE_Prompt = """
78
- <Chat History>
79
- {chat_history}
80
-
81
- <Follow Up Message>
82
- {question}
83
-
84
- <Standalone question>
85
- """
86
- QA_chat_Prompt = """
87
- ユーザーの最新質問に応じて表現を的確に調整し、自然でスムーズな対話を実現し、\
88
- 検索された情報の内容、文脈、コミュニケーションスタイルに適した応答を簡潔に提供してください。
89
- 【ユーザーの会話履歴】
90
- {h_text}
91
- 【ユーザーの最新質問】
92
- {q_text}
93
- 【検索された情報】
94
- {r_text}
95
- 【タスク要求】
96
- - 検索された情報内容を参考に、質問に会話の形で回答すること。
97
- - 原文の作者の文体を模倣すること。
98
- - 原文の作者の思考パターンを模倣すること。
99
- - 簡潔な回答を心がけること。3-5文程度で要点をまとめることを意識してください。
100
- - 文章風ではなく、対話形式で答えること。
101
- """
102
 
103
 
104
  def load_pkl(file_path):
@@ -210,9 +156,12 @@ def max_cosine_similarity(v1, v2_list):
210
  stop=stop_after_attempt(5),
211
  wait=wait_exponential(multiplier=1, min=2, max=10),
212
  )
213
- def generate_item(prompt, sys_prompt, model="gpt-4o-mini"):
 
 
214
  response = client.chat.completions.create(
215
  model=model,
 
216
  messages=[
217
  {
218
  "role": "system",
@@ -389,13 +338,21 @@ class knowledge_class:
389
  break
390
  return retrieve_text, retrieve_title
391
 
392
- def get_answer(self, question_text):
393
 
394
  # get similar info
395
  question_vector = get_embedding(question_text)[0]
396
  info_text, info_title = self.find_top_info(question_vector)
397
- user_prompt = QA_Prompt.format(q_text=question_text, r_text=info_text)
398
- answer_text = generate_item(user_prompt, SYS_Prompt, model="gpt-4o")
 
 
 
 
 
 
 
 
399
  md_text = user_prompt + "\n 応答: \n" + answer_text
400
  timestamp = int(time.time() * 1000)
401
  md_filename = f"./resource/QA_Text_{timestamp}.md"
@@ -404,8 +361,21 @@ class knowledge_class:
404
  file.write(md_text)
405
  return answer_text, info_title, audio_filename
406
 
407
- def get_chat_answer(self, chat_list):
408
  print("all chat list:", chat_list)
 
 
 
 
 
 
 
 
 
 
 
 
 
409
  chat_history = []
410
  for turn in chat_list:
411
  if turn["role"] == "assistant" and turn["metadata"]:
@@ -417,7 +387,10 @@ class knowledge_class:
417
  return None, None, None
418
  if len(chat_history) == 1:
419
  answer_text, info_title, audio_filename = self.get_answer(
420
- chat_history[-1]["content"]
 
 
 
421
  )
422
  return answer_text, info_title, audio_filename
423
  # get history
@@ -448,10 +421,21 @@ class knowledge_class:
448
  # get similar info
449
  question_vector = get_embedding(rewrite_question)[0]
450
  info_text, info_title = self.find_top_info(question_vector)
451
- user_prompt = QA_chat_Prompt.format(
452
- h_text=chat_history_str, q_text=rewrite_question, r_text=info_text
 
 
 
 
 
 
 
 
 
 
 
 
453
  )
454
- answer_text = generate_item(user_prompt, SYS_Prompt, model="gpt-4o")
455
  md_text = user_prompt + "\n 応答: \n" + answer_text
456
  timestamp = int(time.time() * 1000)
457
  md_filename = f"./resource/QA_Text_{timestamp}.md"
 
13
  from openai import OpenAI
14
  from tenacity import retry, stop_after_attempt, wait_exponential
15
 
16
+ from prompts import (
17
+ Common_text,
18
+ Creative_text,
19
+ Full_text,
20
+ QA_chat_Prompt_template,
21
+ QA_Prompt_template,
22
+ REWRITE_Prompt,
23
+ REWRITE_SYS_Prompt,
24
+ SEGMENT_Prompt,
25
+ Short_text,
26
+ STYLE_Prompt,
27
+ SUMMARY_Prompt,
28
+ SYS_Prompt,
29
+ )
30
+
31
  try:
32
  from dotenv import load_dotenv
33
 
 
44
  client = OpenAI(api_key=os.getenv("gpt"))
45
 
46
  #
47
+ audio_client = Session(os.getenv("audio"))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
 
50
  def load_pkl(file_path):
 
156
  stop=stop_after_attempt(5),
157
  wait=wait_exponential(multiplier=1, min=2, max=10),
158
  )
159
+ def generate_item(prompt, sys_prompt, model="gpt-4o-mini", temperature=1.0):
160
+ print("prompt=", prompt)
161
+ print("temperature=", temperature)
162
  response = client.chat.completions.create(
163
  model=model,
164
+ temperature=temperature,
165
  messages=[
166
  {
167
  "role": "system",
 
338
  break
339
  return retrieve_text, retrieve_title
340
 
341
+ def get_answer(self, question_text, creative_prompt, full_prompt, temperature):
342
 
343
  # get similar info
344
  question_vector = get_embedding(question_text)[0]
345
  info_text, info_title = self.find_top_info(question_vector)
346
+
347
+ user_prompt = QA_Prompt_template.format(
348
+ q_text=question_text,
349
+ r_text=info_text,
350
+ c_text=creative_prompt,
351
+ s_text=full_prompt,
352
+ )
353
+ answer_text = generate_item(
354
+ user_prompt, SYS_Prompt, model="gpt-4o", temperature=temperature
355
+ )
356
  md_text = user_prompt + "\n 応答: \n" + answer_text
357
  timestamp = int(time.time() * 1000)
358
  md_filename = f"./resource/QA_Text_{timestamp}.md"
 
361
  file.write(md_text)
362
  return answer_text, info_title, audio_filename
363
 
364
+ def get_chat_answer(self, chat_list, creative_flag, full_flag):
365
  print("all chat list:", chat_list)
366
+ print("creative_flag:", creative_flag)
367
+ print("full_flag:", full_flag)
368
+
369
+ creative_prompt = Common_text
370
+ temperature = 1.0
371
+ if creative_flag:
372
+ creative_prompt = Creative_text
373
+ temperature = 1.2
374
+
375
+ full_prompt = Short_text
376
+ if full_flag:
377
+ full_prompt = Full_text
378
+
379
  chat_history = []
380
  for turn in chat_list:
381
  if turn["role"] == "assistant" and turn["metadata"]:
 
387
  return None, None, None
388
  if len(chat_history) == 1:
389
  answer_text, info_title, audio_filename = self.get_answer(
390
+ chat_history[-1]["content"],
391
+ creative_prompt,
392
+ full_prompt,
393
+ temperature,
394
  )
395
  return answer_text, info_title, audio_filename
396
  # get history
 
421
  # get similar info
422
  question_vector = get_embedding(rewrite_question)[0]
423
  info_text, info_title = self.find_top_info(question_vector)
424
+
425
+ user_prompt = QA_chat_Prompt_template.format(
426
+ h_text=chat_history_str,
427
+ q_text=rewrite_question,
428
+ r_text=info_text,
429
+ c_text=creative_prompt,
430
+ s_text=full_prompt,
431
+ )
432
+
433
+ answer_text = generate_item(
434
+ user_prompt,
435
+ SYS_Prompt,
436
+ model="gpt-4o",
437
+ temperature=temperature,
438
  )
 
439
  md_text = user_prompt + "\n 応答: \n" + answer_text
440
  timestamp = int(time.time() * 1000)
441
  md_filename = f"./resource/QA_Text_{timestamp}.md"
design.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ custom_css = """
2
+ body {
3
+ background-color: #eef2f7;
4
+ margin: 0;
5
+ padding: 0;
6
+ font-family: "Microsoft YaHei", sans-serif;
7
+ }
8
+
9
+ #title-area {
10
+ text-align: center;
11
+ margin-top: 30px;
12
+ margin-bottom: 15px;
13
+ color: #333;
14
+ }
15
+
16
+ #chatbot-container, #references-container, #download-container {
17
+ max-width: 1100px;
18
+ margin: auto;
19
+ background: #f0f7ff;
20
+ }
21
+
22
+ #chatbot-container {
23
+ border-radius: 12px;
24
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
25
+ padding: 10px;
26
+ }
27
+
28
+ #references-container {
29
+ border-radius: 12px;
30
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
31
+ padding: 15px;
32
+ }
33
+
34
+ #submit-btn button {
35
+ background-color: #007bff;
36
+ color: white;
37
+ border-radius: 8px;
38
+ padding: 8px 12px;
39
+ }
40
+
41
+ #update-btn button {
42
+ background-color: #28a745;
43
+ color: white;
44
+ border-radius: 8px;
45
+ padding: 8px 12px;
46
+ }
47
+
48
+ h3 {
49
+ color: #444;
50
+ border-bottom: 2px solid #eee;
51
+ padding-bottom: 8px;
52
+ margin-bottom: 20px;
53
+ }
54
+ """
55
+ custom_head = """
56
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css">
57
+ <script src="https://unpkg.com/@dotlottie/player-component@2.7.12/dist/dotlottie-player.mjs" type="module"></script>
58
+ """
59
+
60
+ js_func = """
61
+ function refresh() {
62
+ const url = new URL(window.location);
63
+
64
+ if (url.searchParams.get('__theme') !== 'light') {
65
+ url.searchParams.set('__theme', 'light');
66
+ window.location.href = url.href;
67
+ }
68
+ }
69
+ """
70
+
71
+ title_html = """
72
+ <div style="display: flex; align-items: center; justify-content: center;">
73
+ <img src="https://cdn.profile-image.st-hatena.com/users/saratoga623/profile.png?1728512391" style="width:50px; height:50px; margin-right:10px;">
74
+ <h1 style="margin: 0;">
75
+ <a href="https://saratoga623.hatenablog.com/" target="_blank" style="text-decoration: none; color: inherit;">
76
+ プロジェクトマネジメント勉強会 <i class='fa fa-lightbulb-o'></i>
77
+ </a>
78
+ </h1>
79
+ </div>
80
+ """
81
+ title_text = """
82
+ <div style="display: flex; align-items: center; justify-content: center;">
83
+ <div>
84
+ <p>経験上、プロジェクトマネジメントで大切だと思っている考え方で</p>
85
+ <p>疑問に答え、音声、参考資料が提供されます</p>
86
+ </div>
87
+ <dotlottie-player src="https://lottie.host/e2d675e6-73f4-4e92-a217-89bf1a4e49d3/cyif3Z9bwS.lottie"
88
+ background="transparent" speed="1" style="width: 150px; height: 150px" loop autoplay></dotlottie-player>
89
+ </div>
90
+ """
91
+ params_text = """
92
+ #### 🔎 回答スタイル
93
+ ユーザーのニーズに合わせて、回答のスタイルを調整することができます。以下はそれぞれの回答タイプの説明です
94
+
95
+ ##### 🎨 創造的な回答
96
+ 創意性を重視した回答です。検索された情報にとらわれすぎず、独自の視点や発想を取り入れ、柔軟かつ豊かな表現で会話を展開します。例え話やユーモア、感情のこもった言い回しなども使用されることがあります。
97
+
98
+ ##### 📘 事実的な回答
99
+ 事実や検索された情報に基づき、正確性と明快さを優先した回答です。主観的な意見や比喩表現は控えめに、情報の整理と伝達に重点を置きます。
100
+
101
+ ##### 📝 詳細な説明
102
+ 質問に対して背景や前提条件を含めながら、複数の段落で論理的に説明するスタイルです。情報の抜けがなく、読者が安心して理解できるよう丁寧に構成されています。特に専門的な話題や複雑な問いに適しています。
103
+
104
+ ##### ✏️ 簡潔な説明
105
+ 要点だけを簡潔にまとめた回答です。時間がないときや、簡単な疑問にすぐ答えたいときに適しています。冗長な説明を避け、核心を押さえることを意識します。
106
+
107
+ 📌 ご希望のスタイルをお選びください。用途や目的に応じて、最適な形式で回答いたします。
108
+ """
prompts.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ SYS_Prompt = """
2
+ あなたは言語の専門家であり、さまざまな話し方や思考パターンを分析し、模倣し、適応することに長けています。
3
+ """
4
+
5
+ SUMMARY_Prompt = """
6
+ あなたは文章の内容を分析する専門家です。
7
+ 以下の文章の要約を作成してください。要約は100字以内で簡潔にまとめてください。
8
+ """
9
+
10
+ STYLE_Prompt = """
11
+ あなたは文章の内容を分析する専門家です。
12
+ 以下の文章内容を分析して、
13
+ 1. 原文の作者の文体を抽出してください。例:敬語、語気、構造、用語など代表的なもの
14
+ 2. 原文の作者の思考パターンを抽出してください。例:論理構成、推論、態度など代表的なもの
15
+ """
16
+ SEGMENT_Prompt = """
17
+ あなたは文章の内容を分析する専門家です。
18
+ 以下の文章を内容に基づいて意味的に段落に分割してください。各段落は独立した文章で、段落ごとに改行を入れてください。
19
+ """
20
+
21
+ QA_Prompt_template = """
22
+ ユーザーの質問に応じて表現を的確に調整し、自然でスムーズな対話を実現し、\
23
+ 検索された情報の内容、文脈、コミュニケーションスタイルに適した応答を提供してください。
24
+
25
+ 【ユーザーの質問】
26
+ {q_text}
27
+ 【検索された情報】
28
+ {r_text}
29
+ 【タスク要求】
30
+ - {c_text}
31
+ - 原文の作者の文体を模倣すること。
32
+ - 原文の思考パターンを模倣すること。
33
+ - {s_text}
34
+ - 文章風ではなく、対話形式で答えること。
35
+ """
36
+ REWRITE_SYS_Prompt = """
37
+ Given a conversation (between Human and Assistant) and a follow up message from Human, \
38
+ rewrite the message to be a standalone question that captures all relevant context \
39
+ from the conversation.
40
+ """
41
+ REWRITE_Prompt = """
42
+ <Chat History>
43
+ {chat_history}
44
+
45
+ <Follow Up Message>
46
+ {question}
47
+
48
+ <Standalone question>
49
+ """
50
+ QA_chat_Prompt_template = """
51
+ ユーザーの最新質問に応じて表現を的確に調整し、自然でスムーズな対話を実現し、\
52
+ 検索された情報の内容、文脈、コミュニケーションスタイルに適した応答を提供してください。
53
+ 【ユーザーの会話履歴】
54
+ {h_text}
55
+ 【ユーザーの最新質問】
56
+ {q_text}
57
+ 【検索された情報】
58
+ {r_text}
59
+ 【タスク要求】
60
+ - {c_text}
61
+ - 原文の作者の文体を模倣すること。
62
+ - 原文の作者の思考パターンを模倣すること。
63
+ - {s_text}
64
+ - 文章風ではなく、対話形式で応答内容だけ、答えること。
65
+ """
66
+ Creative_text = """検索された情報内容を参考に、質問に会話の形で回答すること。
67
+ 必要に応じて検索された情報にとらわれず、自由な発想や独自の視点を取り入れて回答してください。
68
+ 創造性を重視し、会話を豊かにすることを意識してください。
69
+ """
70
+ Common_text = """検索された情報内容を参考に、質問に会話の形で回答すること。
71
+ """
72
+ Short_text = """簡潔な回答を心がけること。3-5文程度で要点をまとめることを意識してください。
73
+ """
74
+ Full_text = """情報の抜けや曖昧な部分がないように、包括的かつ丁寧に回答すること。背景情報や前提条件を補足し、論理的な流れを意識して展開すること。回答は複数の段落で構成し、それぞれの段落が明確なテーマに基づいていること。読者が疑問を抱かず、安心して理解できるよう配慮すること。
75
+ """
resource/2025-04-03-話しながら書く・聞きながら書く技術.mp3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2bf314ff8d4e7bd68d17746b2b454cf0e2b2035c52b8b00739934097ba800876
3
+ size 374909
resource/2025-04-04-質問から始まるコミュニケーション.mp3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:420340bce3a92509d7ffcab6eebf0e643a7a5608c5f1ec19adff74a5da601eed
3
+ size 385358
resource/2025-04-05-局所的な正論だけで戦うと上手くいきません.mp3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e46f68c6462e77394a6ad5a42c976f80a4cb8f21a34176bd7229322cabe5d158
3
+ size 476055
resource/2025-04-07-自分なりに頑張って・・・の罠.mp3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ab75b56c538a0f7c9b11304ac7624eb8f32ded81a9aaa51da7991bd336b564a7
3
+ size 384104
resource/knowledge_data.pkl CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:7a851b435b02bf2f1b0421585e093f0b916ea08008ed838b180de306f7356776
3
- size 17687514
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c8e7fe703ddd333803071b013edeae1da7d0d39d5c9cbf66ca6ed2c7ff82112b
3
+ size 18144304