Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import cohere | |
| import os | |
| from dotenv import load_dotenv | |
| from email.mime.text import MIMEText | |
| import json | |
| from huggingface_hub import list_models | |
| from qdrant_client.models import Distance, VectorParams | |
| from qdrant_client import QdrantClient, models | |
| import uuid | |
| import base64 | |
| import requests | |
| load_dotenv(verbose=True) | |
| # Initialize Qdrant and Cohere clients | |
| client = QdrantClient(url=os.environ.get("QDRANT_URL"), api_key=os.environ.get("QDRANT_API_KEY")) | |
| cohere_client = cohere.Client(api_key=os.environ.get("COHERE_API_KEY")) | |
| co = cohere.ClientV2(api_key=os.environ.get("COHERE_API_KEY")) | |
| '''# OAuthProfile example | |
| class OAuthProfile: | |
| def __init__(self, name, username, profile, picture): | |
| self.name = name | |
| self.username = username | |
| self.profile = profile | |
| self.picture = picture | |
| oauth_profile = OAuthProfile( | |
| name="", | |
| username="", | |
| profile="", | |
| picture="" | |
| )''' | |
| def greeting(profile: gr.OAuthProfile | None) -> str: | |
| if profile is None: | |
| return "⛔️" | |
| else: | |
| print("profile:",profile) | |
| state.value["loginuser"] = profile.name | |
| return f"ようこそ! {profile.name}さん" | |
| #if profile is None: | |
| #return "⛔️" | |
| #return f"ようこそ! {profile.name}さん" | |
| def list_private_models(profile: gr.OAuthProfile | None, oauth_token: gr.OAuthToken | None) -> tuple[str, gr.update, gr.update]: | |
| gr.Textbox(oauth_token) | |
| if oauth_token is None: | |
| state.value["loginuser"] = "HuggingFaceにログインしてください。" | |
| state.value["picture"] = "" | |
| return "HuggingFaceにログインしてください。", gr.update(visible=False), gr.update(visible=False) #, gr.update(visible=False) | |
| #models = [ | |
| #f"{model.id} ({'private' if model.private else 'public'})" | |
| #for model in list_models(author=profile.username, token=oauth_token.token) | |
| #] | |
| userinfo = f"""名前: {profile.name}さん\nID: {profile.username}\nプロファイル: {profile.profile}""" | |
| print("userinfo:",userinfo) | |
| state.value["loginuser"] = userinfo | |
| state.value["picture"] = profile.picture | |
| print("pic:",state.value["picture"],profile.picture) | |
| print("login-user:",state.value["loginuser"],userinfo) | |
| '''global oauth_profile | |
| oauth_profile = OAuthProfile( | |
| name=profile.name, | |
| username=profile.username, | |
| profile=profile.profile, | |
| picture=profile.picture | |
| )''' | |
| #return profile.username, gr.update(visible=True), gr.update(visible=True) #, gr.update(visible=True) | |
| return userinfo, gr.update(visible=True), gr.update(visible=True) #, gr.update(visible=True) | |
| def user_info(state): | |
| print("state:", state) | |
| uinfo = f"""情報: {state["loginuser"]}""" | |
| gr.Info(uinfo) | |
| #gr.Info("情報: Created by RYH International.") | |
| return gr.update(visible=True) | |
| def auth(user_name, password): | |
| encoded = base64.b64encode(password.encode("utf-8")) | |
| # APIエンドポイントのURL | |
| url = "https://www.ryhintl.com/dbjson/getjson?sqlcmd=select userid from ku_credential where password = '" + encoded.decode("utf-8") + "'" | |
| # GETリクエストの例 | |
| response = requests.get(url) | |
| if response.status_code == 200: | |
| credential_id = response.content.decode('utf-8') | |
| parsed_data = json.loads(credential_id) | |
| # useridを取得 | |
| taken_userid = parsed_data[0]["userid"] | |
| if (taken_userid == user_name): | |
| state.value["loginuser"] = user_name | |
| return True # 認証成功 | |
| else: | |
| return False | |
| def process_invitees(state,input_json): | |
| try: | |
| # Parse the JSON input | |
| invitees = json.loads(input_json) | |
| # Generate embeddings using Cohere | |
| response = cohere_client.embed( | |
| texts=[ | |
| 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', '')}" | |
| for note in invitees | |
| ], | |
| model="embed-multilingual-v3.0", | |
| input_type="search_document", | |
| ) | |
| # Upload points to Qdrant | |
| client.upload_points( | |
| collection_name="knowledge_utility", | |
| points=[ | |
| models.PointStruct( | |
| id=uuid.uuid4().hex, | |
| vector=embedding, | |
| payload=note, | |
| ) | |
| for note, embedding in zip(invitees, response.embeddings) | |
| ] | |
| ) | |
| return "Data uploaded successfully!" | |
| except Exception as e: | |
| return f"Error: {str(e)}" | |
| # Function to send Gmail | |
| def send_gmail(mail_from, mail_to, mail_subject, mail_body): | |
| try: | |
| sent_mails = f"From: {mail_from}\nTo: {mail_to}\nSubject: {mail_subject}\nBody:\n{mail_body}\n" | |
| except Exception as e: | |
| sent_mails = f"Error sending mail: {str(e)}" | |
| return sent_mails | |
| # Function to handle search query | |
| def search(state,query: str): | |
| #state["userid"] = "kuuser" | |
| global sent_mails | |
| # Embed query using Cohere | |
| response = cohere_client.embed( | |
| texts=[query], | |
| model="embed-multilingual-v3.0", | |
| input_type="search_query", | |
| ) | |
| # Query Qdrant collection for relevant points | |
| results = client.query_points( | |
| collection_name="knowledge_utility", | |
| query=response.embeddings[0], | |
| limit=1, | |
| ).points | |
| for result in results: | |
| state["score"] = result.score | |
| # Filter points based on similarity threshold | |
| similarity_threshold = 0.1 # Example threshold for filtering | |
| filtered_points = [point for point in results if point.score >= similarity_threshold] | |
| #print("filtered_points:",filtered_points) | |
| # Apply limit to the filtered points | |
| final_limit = len(filtered_points) # Example limit | |
| limited_points = filtered_points[:final_limit] | |
| #print("finals:",final_limit,limited_points) | |
| # Assuming `results` is a list of ScoredPoint objects | |
| payload_list = [] | |
| # Iterate through the limited results and extract payloads | |
| for point in limited_points: | |
| # Access the payload attribute and append it to the list | |
| #print("point:",point) | |
| payload_list.append(point.payload) | |
| #print("payload_list:",payload_list) | |
| # Template for the invitation letter | |
| template = "" | |
| # Prepare results in a user-friendly format | |
| formatted_results = [ | |
| 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']}" | |
| for point in results | |
| ] | |
| #print("formatted_results",formatted_results) | |
| final_result = "\n\n".join(formatted_results) | |
| res = co.chat( | |
| model="command-a-03-2025", | |
| messages=[ | |
| { | |
| "role": "user", | |
| "content": final_result+"を要約してください。 必ず、日本語で答えてください。", | |
| } | |
| ], | |
| ) | |
| final = res.message.content[0].text | |
| # Extract content between "---" | |
| start_marker = "---" | |
| end_marker = "---" | |
| start_index = final.find(start_marker) + len(start_marker) | |
| end_index = final.rfind(end_marker) | |
| return final,state["score"] | |
| # Gradio Blocks Interface | |
| 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: | |
| state = gr.State({ | |
| "userid": "", | |
| "loginuser": "", | |
| "picture": "", | |
| "score": 0 | |
| }) | |
| gr.LoginButton() | |
| # ^ add a login button to the Space | |
| m1 = gr.Markdown() | |
| m2 = gr.Markdown() | |
| ku.load(greeting, inputs=None, outputs=m1) | |
| with gr.Column(): | |
| 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>') | |
| gr.Markdown("# ナレッジ・エージェント") | |
| gr.Markdown("📧 ベクターDBに保存されている知識ベースのインベントリを使用して知識共有します。") | |
| with gr.Sidebar(open=False): | |
| #gr.Image(value=oauth_profile.picture, elem_classes=["custom-image"]) | |
| gr.HTML(""" | |
| <!DOCTYPE html> | |
| <html lang="ja"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Knowledge Utility</title> | |
| <style> | |
| body { | |
| font-family: Arial, sans-serif; | |
| line-height: 1.6; | |
| background-color: #f4f4f9; | |
| color: #333; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| header { | |
| background: #0078d7; | |
| color: #fff; | |
| padding: 1rem 0; | |
| text-align: center; | |
| } | |
| section { | |
| max-width: 800px; | |
| margin: 2rem auto; | |
| padding: 1rem; | |
| background: #fff; | |
| border-radius: 5px; | |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); | |
| } | |
| h1, h2, h3 { | |
| color: #0078d7; | |
| } | |
| ul { | |
| padding-left: 1.5rem; | |
| } | |
| footer { | |
| text-align: center; | |
| padding: 1rem 0; | |
| margin-top: 2rem; | |
| background: #0078d7; | |
| color: white; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <h1 style="color: white;">Knowledge Utility</h1> | |
| <p style="color: white;">知識をシェアし、成長を加速させる。</p> | |
| </header> | |
| <section> | |
| <h2>Knowledge Utilityとは?</h2> | |
| <p> | |
| Knowledge Utilityは、企業や個人が知識を効果的に共有し、成長を促進するためのプラットフォームです。 | |
| データ、アイデア、専門知識をシームレスに交換し、新たな価値を生み出します。 | |
| </p> | |
| <h2>主な機能</h2> | |
| <ul> | |
| <li><strong>情報の検索:</strong> 高速かつ正確なクエリによる知識の取得。</li> | |
| <li><strong>データの登録:</strong> 個人または企業の資産をデータベースに統合。</li> | |
| <li><strong>コラボレーション:</strong> チームやコミュニティ間の知識交換を促進。</li> | |
| </ul> | |
| <h2>メリット</h2> | |
| <p> | |
| Knowledge Utilityを活用することで、効率の向上、意思決定のスピードアップ、そして | |
| 組織の成長が期待できます。 | |
| </p> | |
| </section> | |
| <footer> | |
| <p>© 2025 Knowledge Utility Platform. All rights reserved.</p> | |
| </footer> | |
| </body> | |
| </html> | |
| """) | |
| 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: | |
| with gr.Row(elem_classes=["custom-btn-container"]): # 中央揃え用のクラス | |
| user_btn = gr.Button("情報", elem_classes=["custom-btn"]) | |
| user_btn.click(fn=user_info, inputs=[state], outputs=user_btn) | |
| #user_btn = gr.Button("情報", elem_classes=["custom-btn"]) | |
| #user_btn.click(fn=user_info, inputs=[state], outputs=None) | |
| with gr.Tab("KU 検索") as tab_find: | |
| with gr.Row(): | |
| query_input = gr.Textbox( | |
| label="クエリ", | |
| placeholder="例)物流・流通業界向けの提案書を内容を教えてください。", | |
| info="例)物流・流通業界向けの提案書を内容を教えてください。AI市場の動向を調べています。参考できる事例を教えてください。", | |
| value="経営デジタル・トランスフォーメーション関連のプロジェクトの提案書を書こうと思っています。参考できる事例を教えてください。", | |
| lines=2, | |
| ) | |
| with gr.Column(): | |
| search_button = gr.Button("実行", elem_classes=["custom-btn"]) | |
| clear_button = gr.Button("クリア", elem_classes=["custom-btn"]) | |
| result_output = [gr.Textbox(label="結果", show_copy_button=True),gr.Textbox(label="スコア")] | |
| # Button click events | |
| search_button.click(fn=search, inputs=[state,query_input], outputs=result_output) | |
| clear_button.click(lambda: "", None, result_output) | |
| with gr.Tab("KU インベントリ登録") as tab_reg: | |
| with gr.Row(): | |
| 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"}]""") | |
| output_text = gr.Textbox(label="Result") | |
| with gr.Row(): | |
| submit_button = gr.Button("実行", elem_classes=["custom-btn"]) | |
| submit_button.click(process_invitees, inputs=[state,input_text], outputs=output_text) | |
| # Launch the app | |
| ku.load(list_private_models, inputs=None, outputs=[m2, tab_find, tab_reg]) | |
| ku.launch(favicon_path="favicon.ico",share=True) | |