fudii0921 commited on
Commit
a4fab4c
·
verified ·
1 Parent(s): 2f925d4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +335 -269
app.py CHANGED
@@ -1,156 +1,289 @@
1
- import gradio as gr
2
  import cohere
 
3
  import os
4
  from dotenv import load_dotenv
 
5
  from email.mime.text import MIMEText
6
  import json
7
- from huggingface_hub import list_models
8
 
9
- from qdrant_client.models import Distance, VectorParams
10
- from qdrant_client import QdrantClient, models
11
- import uuid
12
- import base64
13
  import requests
 
 
14
 
15
  load_dotenv(verbose=True)
16
 
17
  # Initialize Qdrant and Cohere clients
18
- client = QdrantClient(url=os.environ.get("QDRANT_URL"), api_key=os.environ.get("QDRANT_API_KEY"))
19
- cohere_client = cohere.Client(api_key=os.environ.get("COHERE_API_KEY"))
20
  co = cohere.ClientV2(api_key=os.environ.get("COHERE_API_KEY"))
 
21
 
 
 
 
 
 
 
22
 
23
- '''# OAuthProfile example
24
- class OAuthProfile:
25
- def __init__(self, name, username, profile, picture):
26
- self.name = name
27
- self.username = username
28
- self.profile = profile
29
- self.picture = picture
30
 
31
- oauth_profile = OAuthProfile(
32
- name="",
33
- username="",
34
- profile="",
35
- picture=""
36
- )'''
37
 
 
 
38
 
39
- def greeting(profile: gr.OAuthProfile | None) -> str:
40
- if profile is None:
41
- return "⛔️"
42
- else:
43
- print("profile:",profile)
44
- state.value["loginuser"] = profile.name
45
- return f"ようこそ! {profile.name}さん"
46
- #if profile is None:
47
- #return "⛔️"
48
- #return f"ようこそ! {profile.name}さん"
49
-
50
-
51
-
52
- def list_private_models(profile: gr.OAuthProfile | None, oauth_token: gr.OAuthToken | None) -> tuple[str, gr.update, gr.update]:
53
- gr.Textbox(oauth_token)
54
- if oauth_token is None:
55
- state.value["loginuser"] = "HuggingFaceにログインしてください。"
56
- state.value["picture"] = ""
57
- return "HuggingFaceにログインしてください。", gr.update(visible=False), gr.update(visible=False) #, gr.update(visible=False)
58
- #models = [
59
- #f"{model.id} ({'private' if model.private else 'public'})"
60
- #for model in list_models(author=profile.username, token=oauth_token.token)
61
- #]
62
- userinfo = f"""名前: {profile.name}さん\nID: {profile.username}\nプロファイル: {profile.profile}"""
63
- print("userinfo:",userinfo)
64
- state.value["loginuser"] = userinfo
65
- state.value["picture"] = profile.picture
66
-
67
- print("pic:",state.value["picture"],profile.picture)
68
- print("login-user:",state.value["loginuser"],userinfo)
69
-
70
- '''global oauth_profile
71
- oauth_profile = OAuthProfile(
72
- name=profile.name,
73
- username=profile.username,
74
- profile=profile.profile,
75
- picture=profile.picture
76
- )'''
77
-
78
- #return profile.username, gr.update(visible=True), gr.update(visible=True) #, gr.update(visible=True)
79
- return userinfo, gr.update(visible=True), gr.update(visible=True) #, gr.update(visible=True)
80
-
81
- def user_info(state):
82
- print("state:", state)
83
- uinfo = f"""情報: {state["loginuser"]}"""
84
- gr.Info(uinfo)
85
- #gr.Info("情報: Created by RYH International.")
86
-
87
- return gr.update(visible=True)
88
 
89
- def auth(user_name, password):
90
- encoded = base64.b64encode(password.encode("utf-8"))
 
91
 
92
- # APIエドポインのURL
93
- url = "https://www.ryhintl.com/dbjson/getjson?sqlcmd=select userid from ku_credential where password = '" + encoded.decode("utf-8") + "'"
 
94
 
95
- # GETリクエストの例
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  response = requests.get(url)
97
- if response.status_code == 200:
98
- credential_id = response.content.decode('utf-8')
99
- parsed_data = json.loads(credential_id)
100
-
101
- # useridを取得
102
- taken_userid = parsed_data[0]["userid"]
103
- if (taken_userid == user_name):
104
- state.value["loginuser"] = user_name
105
- return True # 認証成功
106
- else:
107
- return False
108
-
109
- def process_invitees(state,input_json):
110
- try:
111
- # Parse the JSON input
112
- invitees = json.loads(input_json)
113
-
114
- # Generate embeddings using Cohere
115
- response = cohere_client.embed(
116
- texts=[
117
- f"{note.get('kx_subject', '')}, {note.get('kx_creator', '')}, {note.get('kx_content', '')}, {note.get('kx_industry', '')}, {note.get('kx_kind', '')}, {note.get('kx_category', '')}, {note.get('kx_date', '')}"
118
- for note in invitees
119
- ],
120
- model="embed-multilingual-v3.0",
121
- input_type="search_document",
122
- )
123
 
124
- # Upload points to Qdrant
125
- client.upload_points(
126
- collection_name="knowledge_utility",
127
- points=[
128
- models.PointStruct(
129
- id=uuid.uuid4().hex,
130
- vector=embedding,
131
- payload=note,
132
- )
133
- for note, embedding in zip(invitees, response.embeddings)
134
- ]
135
- )
136
 
137
- return "Data uploaded successfully!"
 
 
 
 
 
 
 
 
138
 
139
- except Exception as e:
140
- return f"Error: {str(e)}"
141
 
142
- # Function to send Gmail
143
  def send_gmail(mail_from, mail_to, mail_subject, mail_body):
 
 
 
 
 
 
 
 
 
 
144
  try:
145
- sent_mails = f"From: {mail_from}\nTo: {mail_to}\nSubject: {mail_subject}\nBody:\n{mail_body}\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  except Exception as e:
147
- sent_mails = f"Error sending mail: {str(e)}"
148
- return sent_mails
 
149
 
150
  # Function to handle search query
151
- def search(state,query: str):
152
- #state["userid"] = "kuuser"
153
-
154
  global sent_mails
155
  # Embed query using Cohere
156
  response = cohere_client.embed(
@@ -166,19 +299,22 @@ def search(state,query: str):
166
  limit=1,
167
  ).points
168
 
169
- for result in results:
170
- state["score"] = result.score
171
-
172
  # Filter points based on similarity threshold
173
- similarity_threshold = 0.1 # Example threshold for filtering
174
  filtered_points = [point for point in results if point.score >= similarity_threshold]
175
 
176
- #print("filtered_points:",filtered_points)
177
-
178
  # Apply limit to the filtered points
179
  final_limit = len(filtered_points) # Example limit
180
  limited_points = filtered_points[:final_limit]
181
- #print("finals:",final_limit,limited_points)
 
 
 
 
 
 
 
 
182
 
183
  # Assuming `results` is a list of ScoredPoint objects
184
  payload_list = []
@@ -186,21 +322,38 @@ def search(state,query: str):
186
  # Iterate through the limited results and extract payloads
187
  for point in limited_points:
188
  # Access the payload attribute and append it to the list
189
- #print("point:",point)
190
  payload_list.append(point.payload)
191
-
192
- #print("payload_list:",payload_list)
193
 
194
  # Template for the invitation letter
195
  template = ""
196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  # Prepare results in a user-friendly format
198
  formatted_results = [
199
  f"kx_subject: {point.payload['kx_subject']}\nkx_content: {point.payload['kx_content']}\nkx_creator: {point.payload['kx_creator']}\nkx_industry: {point.payload['kx_industry']}\nkx_kind: {point.payload['kx_kind']}\nkx_category: {point.payload['kx_category']}\nkx_date: {point.payload['kx_date']}"
200
  for point in results
201
  ]
202
 
203
- #print("formatted_results",formatted_results)
204
  final_result = "\n\n".join(formatted_results)
205
 
206
  res = co.chat(
@@ -220,145 +373,58 @@ def search(state,query: str):
220
  start_index = final.find(start_marker) + len(start_marker)
221
  end_index = final.rfind(end_marker)
222
 
223
- return final,state["score"]
 
 
224
 
225
- # Gradio Blocks Interface
226
- with gr.Blocks(css="footer {visibility: hidden;} .custom-image {width: 64px; height: 64px;} .custom-btn {width: 150px; height: 30px; background-color: lightblue; border-radius: 10px; font-size: 12px; color: #3C82F6;} #header {display: flex; justify-content: space-between; align-items: center; font-size: 24px; font-weight: bold;} #logo {width: 50px; height: 50px;}",title="Knowledge Utility",theme=gr.themes.Glass()) as ku:
227
- state = gr.State({
228
- "userid": "",
229
- "loginuser": "",
230
- "picture": "",
231
- "score": 0
232
- })
233
-
234
- gr.LoginButton()
235
- # ^ add a login button to the Space
236
- m1 = gr.Markdown()
237
- m2 = gr.Markdown()
238
- ku.load(greeting, inputs=None, outputs=m1)
239
-
240
- with gr.Column():
241
- gr.HTML('<div id="header"><span>🛡️ Knowledge Utility</span><img id="logo" src="https://www.ryhintl.com/images/ryhlogo/ryhlogo.png" width="64" height="64" alt="Logo"></div>')
242
- gr.Markdown("# ナレッジ・エージェント")
243
- gr.Markdown("📧 ベクターDBに保存されている知識ベースのインベントリを使用して知識共有します。")
244
-
245
 
246
- with gr.Sidebar(open=False):
247
- #gr.Image(value=oauth_profile.picture, elem_classes=["custom-image"])
248
-
249
- gr.HTML("""
250
- <!DOCTYPE html>
251
- <html lang="ja">
252
- <head>
253
- <meta charset="UTF-8">
254
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
255
- <title>Knowledge Utility</title>
256
- <style>
257
- body {
258
- font-family: Arial, sans-serif;
259
- line-height: 1.6;
260
- background-color: #f4f4f9;
261
- color: #333;
262
- margin: 0;
263
- padding: 0;
264
- }
265
- header {
266
- background: #0078d7;
267
- color: #fff;
268
- padding: 1rem 0;
269
- text-align: center;
270
- }
271
- section {
272
- max-width: 800px;
273
- margin: 2rem auto;
274
- padding: 1rem;
275
- background: #fff;
276
- border-radius: 5px;
277
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
278
- }
279
- h1, h2, h3 {
280
- color: #0078d7;
281
- }
282
- ul {
283
- padding-left: 1.5rem;
284
- }
285
- footer {
286
- text-align: center;
287
- padding: 1rem 0;
288
- margin-top: 2rem;
289
- background: #0078d7;
290
- color: white;
291
- }
292
- </style>
293
- </head>
294
- <body>
295
- <header>
296
- <h1 style="color: white;">Knowledge Utility</h1>
297
- <p style="color: white;">知識をシェアし、成長を加速させる。</p>
298
- </header>
299
- <section>
300
- <h2>Knowledge Utilityとは?</h2>
301
- <p>
302
- Knowledge Utilityは、企業や個人が知識を効果的に共有し、成長を促進するた��のプラットフォームです。
303
- データ、アイデア、専門知識をシームレスに交換し、新たな価値を生み出します。
304
- </p>
305
- <h2>主な機能</h2>
306
- <ul>
307
- <li><strong>情報の検索:</strong> 高速かつ正確なクエリによる知識の取得。</li>
308
- <li><strong>データの登録:</strong> 個人または企業の資産をデータベースに統合。</li>
309
- <li><strong>コラボレーション:</strong> チームやコミュニティ間の知識交換を促進。</li>
310
- </ul>
311
- <h2>メリット</h2>
312
- <p>
313
- Knowledge Utilityを活用することで、効率の向上、意思決定のスピードアップ、そして
314
- 組織の成長が期待できます。
315
- </p>
316
- </section>
317
- <footer>
318
- <p>&copy; 2025 Knowledge Utility Platform. All rights reserved.</p>
319
- </footer>
320
- </body>
321
- </html>
322
- """)
323
-
324
- with gr.Blocks(css=".custom-btn-container { display: flex; justify-content: center; } .custom-btn { width: 150px; height: 30px; background-color: lightblue; border-radius: 10px; font-size: 12px; color: #3C82F6; }") as ubutton:
325
- with gr.Row(elem_classes=["custom-btn-container"]): # 中央揃え用のクラス
326
- user_btn = gr.Button("情報", elem_classes=["custom-btn"])
327
- user_btn.click(fn=user_info, inputs=[state], outputs=user_btn)
328
-
329
- #user_btn = gr.Button("情報", elem_classes=["custom-btn"])
330
-
331
- #user_btn.click(fn=user_info, inputs=[state], outputs=None)
332
-
333
 
334
- with gr.Tab("KU 検索") as tab_find:
335
- with gr.Row():
336
- query_input = gr.Textbox(
337
- label="クエリ",
338
- placeholder="例)物流・流通業界向け提案書を内容を教えてください。",
339
- info="例)物流・流通業界向けの提案書を内容を教えてください。AI市場の動向を調べています。参考できる事例を教えてください。",
340
- value="経営デジタル・トランスフォーメーション関連のプロジェクトの提案書を書こうと思っています。参考できる事例を教えてください。",
341
- lines=2,
342
- )
343
- with gr.Column():
344
- search_button = gr.Button("実行", elem_classes=["custom-btn"])
345
- clear_button = gr.Button("クリア", elem_classes=["custom-btn"])
346
-
347
- result_output = [gr.Textbox(label="結果", show_copy_button=True),gr.Textbox(label="スコア")]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
 
349
- # Button click events
350
- search_button.click(fn=search, inputs=[state,query_input], outputs=result_output)
351
- clear_button.click(lambda: "", None, result_output)
352
 
353
- with gr.Tab("KU インベントリ登録") as tab_reg:
354
- with gr.Row():
355
- input_text = gr.Textbox(label="KU JSON Payroll", lines=10, placeholder="Paste your JSON Payroll here...", info="""[{"kx_subject": "中古車販売���おける現状と問題点", "kx_creator": "username", "kx_content": "事前情報の収集: 顧客動向、問題・課題の想定、3C分析を通じて仮説を策定する。企業動向、顧客動向、競合動向を分析し、仮説を立案する。仮説提案営業の商談フロー: あいさつ、自社紹介、詳細ヒアリング、仮説検証、解決策の提案、ディスカッション、宿題の出し合い、あいさつのステップを踏む。効果的な商談の進め方: 訪問の趣旨を伝え、基本的な質問をし、相手に話させる。仮説をぶつけ、次回の日付と宿題を決める。ヒアリングの技術: 荷主担当者と営業担当者の知識の差を理解し、必要に応じて役割を分担する。ロジスティクスフローを描き、詳細な設問項目を作成する。", "kx_industry": "物流・流通", "kx_kind": "小売", "kx_category": "提案書", "kx_date": "2025/06/02"}]""")
356
- output_text = gr.Textbox(label="Result")
357
- with gr.Row():
358
- submit_button = gr.Button("実行", elem_classes=["custom-btn"])
359
 
360
- submit_button.click(process_invitees, inputs=[state,input_text], outputs=output_text)
361
 
362
- # Launch the app
363
- ku.load(list_private_models, inputs=None, outputs=[m2, tab_find, tab_reg])
364
- ku.launch(favicon_path="favicon.ico",share=True)
 
1
+ from qdrant_client import QdrantClient
2
  import cohere
3
+ import gradio as gr
4
  import os
5
  from dotenv import load_dotenv
6
+ import smtplib
7
  from email.mime.text import MIMEText
8
  import json
 
9
 
10
+ from pptx import Presentation
11
+ from pptx.util import Pt
12
+ import datetime
 
13
  import requests
14
+ from pptx.util import Inches
15
+ from pathlib import Path
16
 
17
  load_dotenv(verbose=True)
18
 
19
  # Initialize Qdrant and Cohere clients
20
+ client = QdrantClient(url=os.environ.get("QDRANT_URL"))
21
+ cohere_client = cohere.Client(api_key=os.environ.get("COHERE_API_KEY")) # Add your Cohere API key here
22
  co = cohere.ClientV2(api_key=os.environ.get("COHERE_API_KEY"))
23
+ sent_mails = ""
24
 
25
+ def create_metapptx(file_name,key):
26
+ url = f"https://www.ryhintl.com/dbjson/getjson?sqlcmd=select * from ku_keyslides where main_title = '"+key+"'"
27
+ response = requests.get(url)
28
+
29
+ mydata = response.content.decode("utf-8")
30
+ result = mydata.replace("[", "").replace("]", "")
31
 
32
+ meta = eval(result)
 
 
 
 
 
 
33
 
34
+ now = datetime.datetime.now() # 現在時刻の取得
35
+ today = now.strftime('%Y年%m月%d日') # 現在時刻を年月曜日で表示
 
 
 
 
36
 
37
+ save_name = file_name # 保存用のパワポのファイル名
38
+ prs = Presentation() # Presentationクラスをインスタンス化
39
 
40
+ # 1枚目
41
+ title_slide_layout = prs.slide_layouts[0]
42
+ slide = prs.slides.add_slide(title_slide_layout)
43
+ title = slide.shapes.title
44
+ subtitle = slide.placeholders[1]
45
+ title.text = meta["main_title"]
46
+ subtitle.text = today
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
+ # フォントサイズを変更
49
+ for paragraph in title.text_frame.paragraphs:
50
+ paragraph.font.size = Pt(24)
51
 
52
+ # フォントサイズを変更
53
+ for paragraph in subtitle.text_frame.paragraphs:
54
+ paragraph.font.size = Pt(10)
55
 
56
+ logo = meta["logo"]
57
+
58
+ print("logo:",logo)
59
+ # リクエストを送信して画像データを取得
60
+ logoresponse = requests.get(logo)
61
+
62
+ logoname = os.path.basename(logo)
63
+
64
+ # ステータスコードを確認
65
+ if logoresponse.status_code == 200:
66
+
67
+ # ローカルファイルに保存
68
+ with open(logoname, 'wb') as file:
69
+ file.write(logoresponse.content)
70
+ corplogoename = "./" + logoname
71
+ picture = slide.shapes.add_picture(corplogoename, Inches(0.2), Inches(0.2), width=Inches(0.5), height=Inches(0.5))
72
+
73
+ if os.path.exists(corplogoename):
74
+ os.remove(corplogoename)
75
+ else:
76
+ picture = slide.shapes.add_picture("./ryhlogo.png", Inches(0.2), Inches(0.2), width=Inches(0.5), height=Inches(0.5))
77
+
78
+ # 2枚目
79
+ title_slide_layout = prs.slide_layouts[1]
80
+ slide = prs.slides.add_slide(title_slide_layout)
81
+ title = slide.shapes.title
82
+ subtitle = slide.placeholders[1]
83
+ title.text = "目次"
84
+ body_shape = slide.placeholders[1]
85
+
86
+ p = body_shape.text_frame.add_paragraph()
87
+ p.text = '1. '+meta["mokuji1"]
88
+ p.level = 1
89
+ p.font.size = Pt(12)
90
+
91
+ p = body_shape.text_frame.add_paragraph()
92
+ p.text = '2. '+meta["mokuji2"]
93
+ p.level = 1
94
+ p.font.size = Pt(12)
95
+
96
+ p = body_shape.text_frame.add_paragraph()
97
+ p.text = '3. '+meta["mokuji3"]
98
+ p.level = 1
99
+ p.font.size = Pt(12)
100
+
101
+ p = body_shape.text_frame.add_paragraph()
102
+ p.text = '4. '+meta["mokuji4"]
103
+ p.level = 1
104
+ p.font.size = Pt(12)
105
+
106
+ # 3枚目
107
+ title_slide_layout = prs.slide_layouts[1]
108
+ slide = prs.slides.add_slide(title_slide_layout)
109
+ title = slide.shapes.title
110
+ title.text = meta["p3_title"]
111
+
112
+ # フォントサイズを変更
113
+ for paragraph in title.text_frame.paragraphs:
114
+ paragraph.font.size = Pt(20)
115
+
116
+ body_shape = slide.placeholders[1]
117
+ p = body_shape.text_frame.add_paragraph()
118
+ p.text = meta["p3_body"]
119
+ p.level = 1
120
+ p.font.size = Pt(12)
121
+
122
+ #picture = slide.shapes.add_picture("https://www.ryhintl.com/images/ryhlogo/ryhlogo.png", Inches(1), Inches(4), width=Inches(3), height=Inches(2))
123
+
124
+ # 4枚目
125
+ title_slide_layout = prs.slide_layouts[1]
126
+ slide = prs.slides.add_slide(title_slide_layout)
127
+ title = slide.shapes.title
128
+ subtitle = slide.placeholders[1]
129
+ title.text = "2. "+meta["p4_title"]
130
+ # フォントサイズを変更
131
+ for paragraph in title.text_frame.paragraphs:
132
+ paragraph.font.size = Pt(20)
133
+
134
+ body_shape = slide.placeholders[1]
135
+ p = body_shape.text_frame.add_paragraph()
136
+ p.text = meta["p4_body1"]
137
+ p.level = 1
138
+ p.font.size = Pt(12)
139
+
140
+ p = body_shape.text_frame.add_paragraph()
141
+ p.text = meta["p4_body2"]
142
+ p.level = 1
143
+ p.font.size = Pt(12)
144
+
145
+ p = body_shape.text_frame.add_paragraph()
146
+ p.text = meta["p4_body3"]
147
+ p.level = 1
148
+ p.font.size = Pt(12)
149
+
150
+ # 5枚目
151
+ title_slide_layout = prs.slide_layouts[1]
152
+ slide = prs.slides.add_slide(title_slide_layout)
153
+ title = slide.shapes.title
154
+ title.text = "3. "+meta["p5_title"]
155
+ # フォントサイズを変更
156
+ for paragraph in title.text_frame.paragraphs:
157
+ paragraph.font.size = Pt(20)
158
+
159
+ body_shape = slide.placeholders[1]
160
+
161
+ p = body_shape.text_frame.add_paragraph()
162
+ p.text = meta["p5_body1"]
163
+ p.level = 1
164
+ p.font.bold = True
165
+ p.font.size = Pt(12)
166
+
167
+ p = body_shape.text_frame.add_paragraph()
168
+ p.text = meta["p5_body2"]
169
+ p.level = 1
170
+ p.font.bold = True
171
+ p.font.size = Pt(12)
172
+
173
+ p = body_shape.text_frame.add_paragraph()
174
+ p.text = meta["p5_body3"]
175
+ p.level = 1
176
+ p.font.bold = True
177
+ p.font.size = Pt(12)
178
+
179
+ # 6枚目
180
+ title_slide_layout = prs.slide_layouts[1]
181
+ slide = prs.slides.add_slide(title_slide_layout)
182
+ title = slide.shapes.title
183
+ subtitle = slide.placeholders[1]
184
+
185
+ title.text = "4."+meta["p6_title"]
186
+ body_shape = slide.placeholders[1]
187
+ subtitle.text = meta["p6_body"]
188
+
189
+ # フォントサイズを変更
190
+ for paragraph in title.text_frame.paragraphs:
191
+ paragraph.font.size = Pt(20)
192
+
193
+ # フォントサイズを変更
194
+ for paragraph in subtitle.text_frame.paragraphs:
195
+ paragraph.font.size = Pt(10)
196
+
197
+ p = body_shape.text_frame.add_paragraph()
198
+ p.text = meta["p6_para1"]
199
+ p.level = 1
200
+ p.font.bold = True
201
+ p.font.size = Pt(12)
202
+
203
+ p = body_shape.text_frame.add_paragraph()
204
+ p.text = meta["p6_para2"]
205
+ p.level = 1
206
+ p.font.bold = True
207
+ p.font.size = Pt(12)
208
+
209
+ # 7枚目
210
+ title_slide_layout = prs.slide_layouts[1]
211
+ slide = prs.slides.add_slide(title_slide_layout)
212
+ title = slide.shapes.title
213
+ title.text = meta["p7_title"]
214
+
215
+ # フォントサイズを変更
216
+ for paragraph in title.text_frame.paragraphs:
217
+ paragraph.font.size = Pt(20)
218
+
219
+ body_shape = slide.placeholders[1]
220
+ p = body_shape.text_frame.add_paragraph()
221
+ p.text = meta["p7_body"]
222
+ p.level = 1
223
+ p.font.size = Pt(12)
224
+
225
+ url = meta["p7_img"]
226
+
227
+ # 保存するファイル名
228
+ fname = os.path.basename(url)
229
+
230
+ filename = "./" + fname
231
+
232
+ # リクエストを送信して画像データを取得
233
  response = requests.get(url)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
 
235
+ # ステータスコードを確認
236
+ if response.status_code == 200:
 
 
 
 
 
 
 
 
 
 
237
 
238
+ # ローカルファイルに保存
239
+ with open(filename, 'wb') as file:
240
+ file.write(response.content)
241
+ picture = slide.shapes.add_picture(filename, Inches(1), Inches(4), width=Inches(3), height=Inches(2))
242
+
243
+ if os.path.exists(filename):
244
+ os.remove(filename)
245
+ else:
246
+ print(f"ダウンロードに失敗しました。ステータスコード: {response.status_code}")
247
 
248
+ prs.save(file_name)
249
+ return f"ファイル '{file_name}' が生成されました!"
250
 
 
251
  def send_gmail(mail_from, mail_to, mail_subject, mail_body):
252
+ '''settings_file = open('settings.json','r')
253
+ settings_data = json.load(settings_file)
254
+
255
+ """ メッセージのオブジェクト """
256
+ msg = MIMEText(mail_body, "plain", "utf-8")
257
+ msg['Subject'] = mail_subject
258
+ msg['From'] = mail_from
259
+ msg['To'] = mail_to
260
+
261
+ # エラーキャッチ
262
  try:
263
+ """ SMTPメールサーバーに接続 """
264
+ smtpobj = smtplib.SMTP('smtp.gmail.com', 587) # SMTPオブジェクトを作成。smtp.gmail.comのSMTPサーバーの587番ポートを設定。
265
+ smtpobj.ehlo() # SMTPサーバとの接続を確立
266
+ smtpobj.starttls() # TLS暗号化通信開始
267
+ gmail_addr = settings_data['gmail_addr'] # Googleアカウント(このアドレスをFromにして送られるっぽい)
268
+ app_passwd = settings_data['app_passwd'] # アプリパスワード
269
+ smtpobj.login(gmail_addr, app_passwd) # SMTPサーバーへログイン
270
+
271
+ """ メール送信 """
272
+ smtpobj.sendmail(mail_from, mail_to, msg.as_string())
273
+
274
+ """ SMTPサーバーとの接続解除 """
275
+ smtpobj.quit()'''
276
+ sent_mails = ""
277
+ try:
278
+ sent_mails = mail_from+"\n"+mail_to+"\n"+mail_subject+"\n"+mail_body+"\n"
279
+
280
  except Exception as e:
281
+ print(e)
282
+
283
+ return sent_mails+"\nメール送信完了\n\n"
284
 
285
  # Function to handle search query
286
+ def search(query: str):
 
 
287
  global sent_mails
288
  # Embed query using Cohere
289
  response = cohere_client.embed(
 
299
  limit=1,
300
  ).points
301
 
 
 
 
302
  # Filter points based on similarity threshold
303
+ similarity_threshold = 0.8 # Example threshold for filtering
304
  filtered_points = [point for point in results if point.score >= similarity_threshold]
305
 
 
 
306
  # Apply limit to the filtered points
307
  final_limit = len(filtered_points) # Example limit
308
  limited_points = filtered_points[:final_limit]
309
+
310
+ '''# Output limited points
311
+ divider = len(limited_points)
312
+ total_score = 0
313
+ for point in limited_points:
314
+ total_score += point.score
315
+ #print(f"ID: {point.id}, Similarity: {point.score}, Payload: {point.payload}")
316
+
317
+ taken_avg = total_score / divider'''
318
 
319
  # Assuming `results` is a list of ScoredPoint objects
320
  payload_list = []
 
322
  # Iterate through the limited results and extract payloads
323
  for point in limited_points:
324
  # Access the payload attribute and append it to the list
 
325
  payload_list.append(point.payload)
 
 
326
 
327
  # Template for the invitation letter
328
  template = ""
329
 
330
+ # Generate invitation letters
331
+ letters = []
332
+ for invitee in payload_list:
333
+ # Replace placeholders in the template with actual invitee information
334
+ letter = template.format(
335
+ 表題=invitee['kx_subject'],
336
+ コンテンツ=invitee['kx_content'],
337
+ 業種=invitee['kx_industry'],
338
+ 作成者=invitee['kx_creator']
339
+ )
340
+
341
+ #send mails
342
+ #sent_mails += send_gmail("info@mycompany.com", invitee['kx_creator'], "ご招待", letter)
343
+ # Append the generated letter to the list
344
+ letters.append(letter)
345
+
346
+ # Print generated letters
347
+ invitations = ""
348
+ for idx, letter in enumerate(letters, start=1):
349
+ invitations += f"Invitation Letter {idx}:\n{letter}\n"
350
+
351
  # Prepare results in a user-friendly format
352
  formatted_results = [
353
  f"kx_subject: {point.payload['kx_subject']}\nkx_content: {point.payload['kx_content']}\nkx_creator: {point.payload['kx_creator']}\nkx_industry: {point.payload['kx_industry']}\nkx_kind: {point.payload['kx_kind']}\nkx_category: {point.payload['kx_category']}\nkx_date: {point.payload['kx_date']}"
354
  for point in results
355
  ]
356
 
 
357
  final_result = "\n\n".join(formatted_results)
358
 
359
  res = co.chat(
 
373
  start_index = final.find(start_marker) + len(start_marker)
374
  end_index = final.rfind(end_marker)
375
 
376
+ # Extract and clean the content
377
+ #content_between = final[start_index:end_index].strip()
378
+ #print("content_between:",content_between)
379
 
380
+ #print("final:","\n\n".join(formatted_results))
381
+ #return "\n\n".join(formatted_results)
382
+ #return final_result,content_between
383
+ #return final_result,invitations,sent_mails,taken_avg
384
+ return final
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
 
386
+ dataid = requests.get("https://www.ryhintl.com/dbjson/getjson?sqlcmd=select main_title from ku_keyslides")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
 
388
+ # Decode the JSON response
389
+ data_str = dataid.content.decode('utf-8')
390
+ data = eval(data_str)
391
+
392
+ # ラベルと値ペアに変換
393
+ choices = [item["main_title"] for item in data]
394
+
395
+
396
+ with gr.Blocks(css="footer {visibility: hidden;} #header {display: flex; justify-content: space-between; align-items: center; font-size: 24px; font-weight: bold;} #logo {width: 50px; height: 50px;}") as pptx:
397
+ with gr.Row():
398
+ gr.Markdown("## Knowledge Utility")
399
+
400
+ with gr.Tabs():
401
+ with gr.Tab("KU"):
402
+ with gr.Row():
403
+ gr.Markdown("📧 ベクターDBに保存されている知識ベースのインベントリを使用して知識共有します。")
404
+ with gr.Row():
405
+ query = gr.Textbox(label="クエリ", info="例)物流・流通業界向けの提案書を内容を教えてください。", value="経営デジタル・トランスフォーメーション関連のプロジェクトの提案書を書こうと思っています。参考できる事例を教えてください。")
406
+ with gr.Row():
407
+ result = gr.Textbox(label="結果", show_copy_button=True)
408
+ with gr.Row():
409
+ submit_btn = gr.Button("実行")
410
+ clear_btn = gr.Button("クリア")
411
+
412
+ submit_btn.click(search, inputs=[query], outputs=[result])
413
+
414
+ with gr.Tab("スライド作成"):
415
+ with gr.Row():
416
+ gr.Markdown("📧 ベクターDBに保存されている知識ベースのインベントリを使用して知識共有します。")
417
+
418
+ with gr.Row():
419
+ file_name_input = gr.Textbox(label="ファイル名を入力してください", value="test.pptx")
420
+ find_key = gr.Dropdown(choices, label="キー・スライドを選択")
421
 
422
+ with gr.Row():
423
+ output = gr.Textbox(label="結果")
 
424
 
425
+ with gr.Row():
426
+ generate_button = gr.Button("生成")
427
+ generate_button.click(create_metapptx, inputs=[file_name_input,find_key], outputs=output)
 
 
 
428
 
429
+ pptx.launch(favicon_path="favicon.ico")
430