fudii0921's picture
Update app.py
64ce671 verified
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>&copy; 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)