fudii0921 commited on
Commit
c8a1c7b
·
verified ·
1 Parent(s): 6113aa8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +306 -102
app.py CHANGED
@@ -1,11 +1,16 @@
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
@@ -17,12 +22,49 @@ from pathlib import Path
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
 
@@ -73,7 +115,7 @@ def create_metapptx(file_name,key):
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]
@@ -248,42 +290,122 @@ def create_metapptx(file_name,key):
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,22 +421,19 @@ def search(query: str):
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,38 +441,21 @@ def search(query: str):
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,47 +475,148 @@ def search(query: str):
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")
@@ -426,5 +629,6 @@ with gr.Blocks(css="footer {visibility: hidden;} #header {display: flex; justify
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
-
 
 
 
 
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
  from pptx import Presentation
16
  from pptx.util import Pt
 
22
  load_dotenv(verbose=True)
23
 
24
  # Initialize Qdrant and Cohere clients
25
+ client = QdrantClient(url=os.environ.get("QDRANT_URL"), api_key=os.environ.get("QDRANT_API_KEY"))
26
+ cohere_client = cohere.Client(api_key=os.environ.get("COHERE_API_KEY"))
27
  co = cohere.ClientV2(api_key=os.environ.get("COHERE_API_KEY"))
28
+
29
+
30
+ '''# OAuthProfile example
31
+ class OAuthProfile:
32
+ def __init__(self, name, username, profile, picture):
33
+ self.name = name
34
+ self.username = username
35
+ self.profile = profile
36
+ self.picture = picture
37
+
38
+ oauth_profile = OAuthProfile(
39
+ name="",
40
+ username="",
41
+ profile="",
42
+ picture=""
43
+ )'''
44
 
45
  def create_metapptx(file_name,key):
46
+ '''meta = {
47
+ "main_title":"AIエージェントについて",
48
+ "mokuji1":"AIエージェントの概要",
49
+ "mokuji2":"主な特徴",
50
+ "mokuji3":"仕組みと応用例",
51
+ "mokuji4":"課題と展望",
52
+ "p3_title":"AIエージェントの概要",
53
+ "p3_body":"AIエージェントは、人間のように自律的に行動し、特定の目標を達成するために設計された高度なAIシステムです。これらのエージェントは、環境から情報を取得し、意思決定を行い、行動を実行する能力を持っています。その結果、複雑なタスクを自動化し、効果的な解決策を提供できます。",
54
+ "p4_title":"主な特徴",
55
+ "p4_body1":"自律性: エージェントは自ら判断を行い、与えられたタスクを進めます。",
56
+ "p4_body2":"適応性: 環境の変化に応じて行動を調整し、新しい状況に適応します。",
57
+ "p4_body3":"連携能力: 複数のエージェントが協力してタスクを実行し、より複雑な問題に対応します。",
58
+ "p5_title":"応用例",
59
+ "p5_body1":"バーチャルアシスタント: 自然言語処理を活用してカスタマーサポートやスケジュール管理を支援。",
60
+ "p5_body2":"自動運転: 車両が周囲の状況を検出し、安全なルートを計画。",
61
+ "p5_body3":"医療分野: 症状を分析し、診断をサポート。",
62
+ "p6_title":"課題と展望",
63
+ "p6_body":"Issues & Prospect",
64
+ "p6_para1":"課題:・プライバシー問題や倫理的懸念。・誤った判断によるリスク。",
65
+ "p6_para2":"展望:・生成AIと統合することで、より高度な機能を実現。・新しい産業への適用範囲の拡大。"
66
+ }'''
67
+
68
  url = f"https://www.ryhintl.com/dbjson/getjson?sqlcmd=select * from ku_keyslides where main_title = '"+key+"'"
69
  response = requests.get(url)
70
 
 
115
  if os.path.exists(corplogoename):
116
  os.remove(corplogoename)
117
  else:
118
+ picture = slide.shapes.add_picture("/Users/richardhuh/Desktop/stock_research/ryhlogo.png", Inches(0.2), Inches(0.2), width=Inches(0.5), height=Inches(0.5))
119
 
120
  # 2枚目
121
  title_slide_layout = prs.slide_layouts[1]
 
290
  prs.save(file_name)
291
  return f"ファイル '{file_name}' が生成されました!"
292
 
 
 
 
293
 
294
+ def greeting(profile: gr.OAuthProfile | None) -> str:
295
+ if profile is None:
296
+ return "⛔️"
297
+ else:
298
+ print("profile:",profile)
299
+ state.value["loginuser"] = profile.name
300
+ return f"ようこそ! {profile.name}さん"
301
+ #if profile is None:
302
+ #return "⛔️"
303
+ #return f"ようこそ! {profile.name}さん"
304
+
305
+
306
+
307
+ def list_private_models(profile: gr.OAuthProfile | None, oauth_token: gr.OAuthToken | None) -> tuple[str, gr.update, gr.update]:
308
+ gr.Textbox(oauth_token)
309
+ if oauth_token is None:
310
+ state.value["loginuser"] = "HuggingFaceにログインしてください。"
311
+ state.value["picture"] = ""
312
+ return "HuggingFaceにログインしてください。", gr.update(visible=False), gr.update(visible=False) #, gr.update(visible=False)
313
+ #models = [
314
+ #f"{model.id} ({'private' if model.private else 'public'})"
315
+ #for model in list_models(author=profile.username, token=oauth_token.token)
316
+ #]
317
+ userinfo = f"""名前: {profile.name}さん\nID: {profile.username}\nプロファイル: {profile.profile}"""
318
+ print("userinfo:",userinfo)
319
+ state.value["loginuser"] = userinfo
320
+ state.value["picture"] = profile.picture
321
+
322
+ print("pic:",state.value["picture"],profile.picture)
323
+ print("login-user:",state.value["loginuser"],userinfo)
324
+
325
+ '''global oauth_profile
326
+ oauth_profile = OAuthProfile(
327
+ name=profile.name,
328
+ username=profile.username,
329
+ profile=profile.profile,
330
+ picture=profile.picture
331
+ )'''
332
+
333
+ #return profile.username, gr.update(visible=True), gr.update(visible=True) #, gr.update(visible=True)
334
+ return userinfo, gr.update(visible=True), gr.update(visible=True) #, gr.update(visible=True)
335
+
336
+ def user_info(state):
337
+ print("state:", state)
338
+ uinfo = f"""情報: {state["loginuser"]}"""
339
+ gr.Info(uinfo)
340
+ #gr.Info("情報: Created by RYH International.")
341
+
342
+ return gr.update(visible=True)
343
 
344
+ def auth(user_name, password):
345
+ encoded = base64.b64encode(password.encode("utf-8"))
346
+
347
+ # APIエンドインのURL
348
+ url = "https://www.ryhintl.com/dbjson/getjson?sqlcmd=select userid from ku_credential where password = '" + encoded.decode("utf-8") + "'"
349
+
350
+ # GETリクエストの
351
+ response = requests.get(url)
352
+ if response.status_code == 200:
353
+ credential_id = response.content.decode('utf-8')
354
+ parsed_data = json.loads(credential_id)
355
+
356
+ # useridを取得
357
+ taken_userid = parsed_data[0]["userid"]
358
+ if (taken_userid == user_name):
359
+ state.value["loginuser"] = user_name
360
+ return True # 認証成功
361
+ else:
362
+ return False
363
+
364
+ def process_invitees(state,input_json):
365
  try:
366
+ # Parse the JSON input
367
+ invitees = json.loads(input_json)
368
+
369
+ # Generate embeddings using Cohere
370
+ response = cohere_client.embed(
371
+ texts=[
372
+ 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', '')}"
373
+ for note in invitees
374
+ ],
375
+ model="embed-multilingual-v3.0",
376
+ input_type="search_document",
377
+ )
378
+
379
+ # Upload points to Qdrant
380
+ client.upload_points(
381
+ collection_name="knowledge_utility",
382
+ points=[
383
+ models.PointStruct(
384
+ id=uuid.uuid4().hex,
385
+ vector=embedding,
386
+ payload=note,
387
+ )
388
+ for note, embedding in zip(invitees, response.embeddings)
389
+ ]
390
+ )
391
+
392
+ return "Data uploaded successfully!"
393
 
394
  except Exception as e:
395
+ return f"Error: {str(e)}"
396
+
397
+ # Function to send Gmail
398
+ def send_gmail(mail_from, mail_to, mail_subject, mail_body):
399
+ try:
400
+ sent_mails = f"From: {mail_from}\nTo: {mail_to}\nSubject: {mail_subject}\nBody:\n{mail_body}\n"
401
+ except Exception as e:
402
+ sent_mails = f"Error sending mail: {str(e)}"
403
+ return sent_mails
404
 
405
  # Function to handle search query
406
+ def search(state,query: str):
407
+ #state["userid"] = "kuuser"
408
+
409
  global sent_mails
410
  # Embed query using Cohere
411
  response = cohere_client.embed(
 
421
  limit=1,
422
  ).points
423
 
424
+ for result in results:
425
+ state["score"] = result.score
426
+
427
  # Filter points based on similarity threshold
428
+ similarity_threshold = 0.1 # Example threshold for filtering
429
  filtered_points = [point for point in results if point.score >= similarity_threshold]
430
 
431
+ #print("filtered_points:",filtered_points)
432
+
433
  # Apply limit to the filtered points
434
  final_limit = len(filtered_points) # Example limit
435
  limited_points = filtered_points[:final_limit]
436
+ #print("finals:",final_limit,limited_points)
 
 
 
 
 
 
 
 
437
 
438
  # Assuming `results` is a list of ScoredPoint objects
439
  payload_list = []
 
441
  # Iterate through the limited results and extract payloads
442
  for point in limited_points:
443
  # Access the payload attribute and append it to the list
444
+ #print("point:",point)
445
  payload_list.append(point.payload)
446
+
447
+ #print("payload_list:",payload_list)
448
 
449
  # Template for the invitation letter
450
  template = ""
451
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
452
  # Prepare results in a user-friendly format
453
  formatted_results = [
454
  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']}"
455
  for point in results
456
  ]
457
 
458
+ #print("formatted_results",formatted_results)
459
  final_result = "\n\n".join(formatted_results)
460
 
461
  res = co.chat(
 
475
  start_index = final.find(start_marker) + len(start_marker)
476
  end_index = final.rfind(end_marker)
477
 
478
+ return final,state["score"]
 
 
 
 
 
 
 
 
 
 
479
 
480
+ # Gradio Blocks Interface
481
+ 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:
482
+ state = gr.State({
483
+ "userid": "",
484
+ "loginuser": "",
485
+ "picture": "",
486
+ "score": 0
487
+ })
488
+
489
+ gr.LoginButton()
490
+ # ^ add a login button to the Space
491
+ m1 = gr.Markdown()
492
+ m2 = gr.Markdown()
493
+ ku.load(greeting, inputs=None, outputs=m1)
494
+
495
+ with gr.Column():
496
+ 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>')
497
+ gr.Markdown("# ナレッジ・エージェント")
498
+ gr.Markdown("📧 ベクターDBに保存されている知識ベースのインベントリを使用して知識共有します。")
499
+
500
 
501
+ with gr.Sidebar(open=False):
502
+ #gr.Image(value=oauth_profile.picture, elem_classes=["custom-image"])
503
+
504
+ gr.HTML("""
505
+ <!DOCTYPE html>
506
+ <html lang="ja">
507
+ <head>
508
+ <meta charset="UTF-8">
509
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
510
+ <title>Knowledge Utility</title>
511
+ <style>
512
+ body {
513
+ font-family: Arial, sans-serif;
514
+ line-height: 1.6;
515
+ background-color: #f4f4f9;
516
+ color: #333;
517
+ margin: 0;
518
+ padding: 0;
519
+ }
520
+ header {
521
+ background: #0078d7;
522
+ color: #fff;
523
+ padding: 1rem 0;
524
+ text-align: center;
525
+ }
526
+ section {
527
+ max-width: 800px;
528
+ margin: 2rem auto;
529
+ padding: 1rem;
530
+ background: #fff;
531
+ border-radius: 5px;
532
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
533
+ }
534
+ h1, h2, h3 {
535
+ color: #0078d7;
536
+ }
537
+ ul {
538
+ padding-left: 1.5rem;
539
+ }
540
+ footer {
541
+ text-align: center;
542
+ padding: 1rem 0;
543
+ margin-top: 2rem;
544
+ background: #0078d7;
545
+ color: white;
546
+ }
547
+ </style>
548
+ </head>
549
+ <body>
550
+ <header>
551
+ <h1 style="color: white;">Knowledge Utility</h1>
552
+ <p style="color: white;">知識をシェアし、成長を加速させる。</p>
553
+ </header>
554
+ <section>
555
+ <h2>Knowledge Utilityとは?</h2>
556
+ <p>
557
+ Knowledge Utilityは、企業や個人が知識を効果的に共有し、成長を促進するためのプラットフォームです。
558
+ データ、アイデア、専門知識をシームレスに交換し、新たな価値を生み出します。
559
+ </p>
560
+ <h2>主な機能</h2>
561
+ <ul>
562
+ <li><strong>情報の検索:</strong> 高速かつ正確なクエリによる知識の取得。</li>
563
+ <li><strong>データの登録:</strong> 個人または企業の資産をデータベースに統合。</li>
564
+ <li><strong>コラボレーション:</strong> チームやコミュニティ間の知識交換を促進。</li>
565
+ </ul>
566
+ <h2>メリット</h2>
567
+ <p>
568
+ Knowledge Utilityを活用することで、効率の向上、意思決定のスピードアップ、そして
569
+ 組織の成長が期待できます。
570
+ </p>
571
+ </section>
572
+ <footer>
573
+ <p>&copy; 2025 Knowledge Utility Platform. All rights reserved.</p>
574
+ </footer>
575
+ </body>
576
+ </html>
577
+ """)
578
+
579
+ 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:
580
+ with gr.Row(elem_classes=["custom-btn-container"]): # 中央揃え用のクラス
581
+ user_btn = gr.Button("情報", elem_classes=["custom-btn"])
582
+ user_btn.click(fn=user_info, inputs=[state], outputs=user_btn)
583
+
584
+ #user_btn = gr.Button("情報", elem_classes=["custom-btn"])
585
+
586
+ #user_btn.click(fn=user_info, inputs=[state], outputs=None)
587
+
588
 
589
+ with gr.Tab("KU 検索") as tab_find:
590
+ with gr.Row():
591
+ query_input = gr.Textbox(
592
+ label="クエリ",
593
+ placeholder="例)物流・流通業界向けの提案書を内容を教えてください。",
594
+ info="例)物流・流通業界向けの提案書を内容を教えてください。AI市場の動向を調べています。参考できる事例を教えてください。",
595
+ value="経営デジタル・トランスフォーメーション関連のプロジェクトの提案書を書こうと思っています。参考できる事例を教えてください。",
596
+ lines=2,
597
+ )
598
+ with gr.Column():
599
+ search_button = gr.Button("実行", elem_classes=["custom-btn"])
600
+ clear_button = gr.Button("クリア", elem_classes=["custom-btn"])
601
+
602
+ result_output = [gr.Textbox(label="結果", show_copy_button=True),gr.Textbox(label="スコア")]
603
 
604
+ # Button click events
605
+ search_button.click(fn=search, inputs=[state,query_input], outputs=result_output)
606
+ clear_button.click(lambda: "", None, result_output)
607
 
608
+ with gr.Tab("KU インベントリ登録") as tab_reg:
609
+ with gr.Row():
610
+ 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"}]""")
611
+ output_text = gr.Textbox(label="Result")
612
+ with gr.Row():
613
+ submit_button = gr.Button("実行", elem_classes=["custom-btn"])
 
 
 
 
 
614
 
615
+ submit_button.click(process_invitees, inputs=[state,input_text], outputs=output_text)
616
 
617
+ with gr.Tab("スライド作成"):
618
  with gr.Row():
619
+ gr.Markdown("📧 ベクターDBに保存されている知識ベースのインベントリを使用してスライドを作成します。")
620
 
621
  with gr.Row():
622
  file_name_input = gr.Textbox(label="ファイル名を入力してください", value="test.pptx")
 
629
  generate_button = gr.Button("生成")
630
  generate_button.click(create_metapptx, inputs=[file_name_input,find_key], outputs=output)
631
 
632
+ # Launch the app
633
+ ku.load(list_private_models, inputs=None, outputs=[m2, tab_find, tab_reg])
634
+ ku.launch(favicon_path="favicon.ico",share=True)