import gradio as gr
import re
import hashlib
import mysql.connector as mydb
import time
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import japanize_matplotlib
from google import genai
from google.genai import types
import os
from dotenv import load_dotenv
import tempfile
import os
import msal
import json
import logging
import logging.handlers
import requests
matplotlib.use('Agg') # 重要な設定
load_dotenv(verbose=True)
try:
with open("parameters.json") as f:
config = json.load(f)
except FileNotFoundError:
print("Error: parameters.json not found. Please create the file.")
config = {}
# msal.ConfidentialClientApplicationのインスタンス化
if config:
app = msal.ConfidentialClientApplication(
config["client_id"], authority=config["authority"],
client_credential=config["secret"],
)
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
eval_kijyun = "評価会議のための質問事項(ディスカッションガイド)1. イントロダクションと全体像の確認対象質問・論点目的評価者「この評価レポートの意図は、過去を裁くことではなく、今後の成長を最大化することです。まず、レポートの全体的な評価について、あなたの最初の感想を教えてください。」建設的な雰囲気を作り、自己評価と他者評価のギャップを認識させる。評価者「期間を通じて、あなたが設定していた最も重要な目標は何でしたか?その目標達成について、自己評価はどの程度ですか?」評価の焦点を合わせ、本人の認識を明確にする。2. 業績評価に関する質問(成果の深掘り)対象質問・論点目的コンサルタント「期間中、あなたが最も価値を提供できたと実感しているプロジェクト(または成果物)はどれですか?具体的にクライアントにどのようなインパクトを与えましたか?」本人が誇る成果を確認し、具体的な事例を掘り下げる。評価者「『プロジェクト〇〇』での目標達成度は高いと評価しましたが、その成功の**最も大きな要因(KFS)**は何だったと考えますか?」成功の再現性を高めるための要因分析を促す。評価者「逆に、目標を達成できなかった、あるいは難航したプロジェクトについて、主要なボトルネックは何でしたか?それはコントロール可能な要因とコントロール不能な要因のどちらでしたか?」失敗からの学びを引き出し、客観的な状況分析力を評価する。評価者「ファームへの貢献(ナレッジ共有、採用など)で特に注力した点はありますか?その活動を通じてチームにどのような変化をもたらしましたか?」チーム・組織へのコミットメントと影響力を評価する。3. 能力評価に関する質問(スキルの具体化)対象質問・論点目的評価者「能力評価において『問題解決・論理的思考力』を高く評価しましたが、これを最もよく示していた具体的な行動や発言を一つ教えてください。」評価者の判断根拠を共有し、評価の納得度を高める。コンサルタント「次期に向けて、コンサルタントとして最も強化が必要だと感じているスキルは何ですか?なぜそれが重要だと考えますか?」課題意識と成長意欲、そして自己認識の正確さを評価する。評価者「あなたの提案資料は非常に論理的でしたが、**『伝達力』**の項目で改善点があると評価したのは、どのような場面(例:クライアントとの交渉、経営層へのプレゼン)でのことですか?」定性的な評価について、具体的な場面(コンテキスト)を示してフィードバックする。4. 行動評価に関する質問(プロセスとプロフェッショナリズム)対象質問・論点目的評価者「『プロジェクトA』の緊迫した状況下で、あなたはチームに対してどのようなリーダーシップを発揮しましたか?具体的な行動を教えてください。」プレッシャー下での行動やチームへの影響力を評価する。コンサルタント「期間中の業務プロセスを振り返って、より良い結果を出すために一つだけ変えられるとしたら、どの時点のどの行動を変えますか?」振り返りから改善につなげる内省力と、行動の重要性を理解しているかを評価する。評価者「クライアントとのコミュニケーションにおいて、特に信頼関係を深めるために意識的に行っていたことは何ですか?結果としてどうなりましたか?」クライアントリレーション構築における意識的な努力と、その結果を評価する。5. 総括とネクストステップ(キャリア開発)対象質問・論点目的評価者「総合的に見て、次の職位(例:マネージャー)へ昇進するために、現時点で最も不足していると判断するスキルや行動は何ですか? 具体的な基準に照らして説明します。」次の職位への期待値(卒業要件)を明確に伝え、ギャップを埋めるための目標設定につなげる。コンサルタント「この評価結果を踏まえ、次期の重点目標としてレポートに記載した内容(専門性向上やキャリアゴール)は、あなたのキャリアパスと合致していますか?」個人の目標とファームのニーズとの整合性を確認する。コンサルタント「目標達成のために、ファーム(評価者やチーム)にどのようなサポートやリソースを期待しますか?」育成計画に必要なリソースや環境整備について具体的に議論する。評価者「この評価レビューを通じて、他に懸念点や疑問点はありますか?私からのフィードバックに納得できない点があれば、ぜひ教えてください。」相互理解を深め、オープンな関係を維持したまま会議を終える。"
grounding_tool = types.Tool(
google_search=types.GoogleSearch()
)
#configs = types.GenerateContentConfig(
# tools=[grounding_tool]
#)
template = """
パフォーマンスレポート:名前
1. 基本情報
シニアアソシエイト
xxxx年4月1日 〜 xxxx年3月31日
評価者名前
xxxx年xx月xx日
2. プロジェクト別評価
💼 XXXコスト削減プロジェクト
大手製造業のコスト構造改革
主要プロジェクトの達成目標
クライアント満足度
実行力・責任感
🧪 XXX化学新規事業戦略策定プロジェクト
新規事業参入戦略
問題解決・論理的思考力
専門知識とスキル
リーダーシップ・影響力
3. ファームへの貢献と総合評価
ファームへの貢献
チームワーク・協調性
総括(評価者記入欄)
4. 今後の目標とネクストステップ
専門性向上
目標設定: M&A後のPMI(Post Merger Integration)に関する専門知識とケーススタディを習得し、関連プロジェクトに参画する。
サポート・トレーニング計画: 外部M&A専門家によるトレーニングプログラム(全3回)への参加。プロジェクトB'のPMIフェーズへのアサインメント。
キャリアゴール
目標設定: 評価期間内にマネージャーへのプロモーションを目指す。そのために、チームメンバー2名に対し、デリバラブル作成に関するメンタリングを最低3ヶ月実施する。
サポート・トレーニング計画:
佐藤(評価者)による月次の1on1ミーティングを設定し、委譲と育成の進捗をレビューする。シニアマネージャーが主催するリーダーシップ・ワークショップへの招待。
"""
class DoSwitch:
def __init__(self):
# 状態(state)をインスタンス変数として保持
self.is_logged = False
self.first_exec = False
self.lastlog = ""
def log_on(self):
self.is_logged = True
def log_oout(self):
self.log_on = False
def first_executed(self):
self.first_exec = True
my_switch = DoSwitch()
def change_input(prompt):
if len(prompt) > 0:
return gr.update(visible=True)
else:
return gr.update(visible=False)
def generate_review(prompt, scores, userid):
#global chart_path
chart_path = generate_chart(scores, userid)
#print("chart_path",chart_path)
print("chart_path",chart_path)
current_chart_path = chart_path
#current_chart_path = 'https://www.ryhintl.com/images/curchart.png'
global template
template = '''
パフォーマンスレポート:名前 (静的版)
1. 基本情報
シニアアソシエイト
xxxx年4月1日 〜 xxxx年3月31日
評価者名前
xxxx年xx月xx日
2. プロジェクト別評価
💼 XXXコスト削減プロジェクト
大手製造業のコスト構造改革
主要プロジェクトの達成目標
クライアント満足度
実行力・責任感
🧪 XXX化学新規事業戦略策定プロジェクト
新規事業参入戦略
問題解決・論理的思考力
専門知識とスキル
リーダーシップ・影響力
4. ファームへの貢献と総合評価
ファームへの貢献
チームワーク・協調性
総括(評価者記入欄)
5. 今後の目標とネクストステップ
専門性向上
目標設定: M&A後のPMI(Post Merger Integration)に関する専門知識とケーススタディを習得し、関連プロジェクトに参画する。
サポート・トレーニング計画: 外部M&A専門家によるトレーニングプログラム(全3回)への参加。プロジェクトB'のPMIフェーズへのアサインメント。
キャリアゴール
目標設定: 評価期間内にマネージャーへのプロモーションを目指す。そのために、チームメンバー2名に対し、デリバラブル作成に関するメンタリングを最低3ヶ月実施する。
サポート・トレーニング計画:
佐藤(評価者)による月次の1on1ミーティングを設定し、委譲と育成の進捗をレビューする。シニアマネージャーが主催するリーダーシップ・ワークショップへの招待。
'''
try:
final_prompt = prompt + f'{eval_kijyun}に基づいて{prompt}に記載されているコンサルタントのパフォーマンスをプロジェクト毎に分けて評価してください。必ず、評価者の総合評価を詳しく記載してください。答えは{template}に合わせてHTML形式にしてください'
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=final_prompt,
#config=config,
)
#print(response.text)
final_html = response.text
#final_html = final_html.replace("```html", "")
#final_html = final_html.replace("```", "")
fin1 = final_html.find('```html')
fin2 = final_html.rfind('```')
final_html = final_html[fin1+7:fin2-3]
#print("final_html:",final_html)
with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".html", encoding="utf-8") as tmp_file:
# レポート内容をファイルに書き込む
#pdfkit.from_string(final_html, tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".pdf", encoding="utf-8").name)
tmp_file.write(final_html)
# ファイルパスを取得
file_path = tmp_file.name
weburl = put_file_to_graph_api(f"https://graph.microsoft.com/v1.0/sites/richardhuh.sharepoint.com,049de070-ff59-4a3e-b236-909dd06d18dc,928892cd-d109-40fe-9c67-c6fb82eb3b8d/drives/b!cOCdBFn_PkqyNpCd0G0Y3M2SiJIJ0f5AnGfG-4LrO428BidG9UKZQ4RHLePvALXz/root:/Work/{tmp_file.name}:/content", file_path)
#print("weburl:", weburl)
return final_html, ''
#return final_html,file_path
except Exception as e:
return f"An error occurred: {e}", None
def update_prompt_suffix(prompt_suffix):
if prompt_suffix == "投資判断用の要約":
return temp_in
else:
return ""
def get_access_token() -> dict:
"""MSALを使用してアクセストークンを取得またはキャッシュから読み込む"""
if not config:
raise Exception("Configuration (parameters.json) is missing.")
result = app.acquire_token_silent(config["scope"], account=None)
if not result:
logging.info("No suitable token exists in cache. Let's get a new one from AAD.")
result = app.acquire_token_for_client(scopes=config["scope"])
return result
def get_some_data_from_graph_api(endpoint: str) -> None:
"""Graph APIからデータを取得(今回は未使用だが残しておく)"""
access_token = get_access_token()
if "access_token" in access_token:
graph_data = requests.get(
endpoint,
headers={'Authorization': 'Bearer ' + access_token['access_token']}, ).json()
return graph_data
else:
raise Exception("===Failed to call MS Graph API. See stderr for details.===")
def put_file_to_graph_api(endpoint: str, file_path: str) -> dict:
"""Graph APIを使用してファイルをOneDrive/SharePointにアップロードする"""
access_token = get_access_token()
if "access_token" in access_token:
try:
with open(file_path, 'rb') as f:
graph_data = requests.put(
endpoint,
headers={'Authorization': 'Bearer ' + access_token['access_token']},
data=f).json()
print("graph_data:", graph_data.get('webUrl'))
global fileurl
# アップロードされたファイルのURLをグローバル変数に保存
fileurl = graph_data.get('webUrl', 'URL not available')
#print("fileurl:", fileurl)
return fileurl
#return graph_data
except Exception as e:
print(f"File upload error: {e}")
raise Exception(f"===Failed to upload file to MS Graph API. Details: {e}===")
else:
raise Exception("===Failed to call MS Graph API. See stderr for details.===")
def open_signup_window():
"""
gr.HTMLコンポーネントを使って、HTMLのリンクをボタンのように表示します。
"""
# HTMLのaタグを生成し、target="_blank"で新しいタブを開くように指定します。
# このリンクをCSSでボタンのようにスタイルします。
# この文字列全体がHTMLとしてGradioにレンダリングされます。
html_content = """
"""
return gr.HTML(html_content)
def clean_text(text):
# 改行とタブを削除
return text.replace('\n', '').replace('\t', '').replace(' ', '')
def generate_chart(scores: str, userid: str):
#global uid
uid = userid
print('chart-uid:',uid)
#print("uid",uid)
#scores = [int(score) for score in scores.split(",")]
scores = eval(scores)
labels = [
'主要プロジェクトの達成目標',
'クライアント満足度',
'実行力・責任感',
'問題解決・論理的思考力',
'専門知識とスキル',
'リーダーシップ・影響力'
]
# データの準備:レーダーチャートは閉じたプロットが必要なため、最初のデータをリストの最後に追加
num_vars = len(labels)
data = np.concatenate((scores, [scores[0]]))
angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False)
angles = np.concatenate((angles, [angles[0]]))
fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(polar=True))
# グラフのプロット
ax.plot(angles, data, color='#c9b16e', linewidth=2, linestyle='solid', label='評価スコア')
# 領域の塗りつぶし
ax.fill(angles, data, color='#c9b16e', alpha=0.3)
# 軸ラベルの設定
ax.set_xticks(angles[:-1])
ax.set_xticklabels(labels, size=12, y=0.01) # ラベルの位置調整
# 目盛りの設定 (0から10まで)
ax.set_yticks(np.arange(0, 11, 2))
ax.set_ylim(0, 10) # 評価の最大値 (10点満点)
ax.set_yticklabels([str(i) for i in np.arange(0, 11, 2)], color="grey", size=10)
# タイトル
ax.set_title('パフォーマンス KPI サマリー', size=16, color='#0d1a2f', y=1.1)
# グリッド線のスタイル調整
ax.grid(True, linestyle='--', alpha=0.7)
# 凡例を表示
ax.legend(loc='upper right', bbox_to_anchor=(0.1, 0.1))
#plt.savefig(f'./{uid}.png', dpi=300)
plt.savefig(f'./{uid}.png', dpi=300)
#return '/Library/WebServer/Documents/charts/{uid}.png'
return f'http://localhost/charts/{uid}.png'
def validate_username(username):
if len(username) < 4:
return "ユーザー名は4文字以上である必要があります"
if not re.match("^[a-zA-Z0-9_]+$", username):
return "ユーザー名には文字、数字、アンダースコアのみ使用できます"
return None
def validate_email(email):
if not re.match(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$", email):
return "有効なメールアドレスを入力してください"
return None
def validate_password(password):
if len(password) < 8:
return "パスワードは8文字以上でなければなりません"
if not any(char.isdigit() for char in password):
return "パスワードには少なくとも1つの数字を含める必要があります"
if not any(char.isupper() for char in password):
return "パスワードには少なくとも1つの大文字を含める必要があります"
return None
def validate_phone(phone):
if phone and not re.match(r"^\+?[0-9\s\-]+$", phone):
return "有効な電話番号を入力してください"
return None
def hash_password(password):
return hashlib.sha256(password.encode()).hexdigest()
def login_user(username, password):
conn = mydb.connect(
host='www.ryhintl.com',
port='36000',
user='smairuser',
password='smairuser',
database='smair'
)
c = conn.cursor()
hashed_pw = hash_password(password)
sqlcmd = "SELECT * FROM gyoseki_users WHERE username = '"+username+"' AND password = '"+hashed_pw+"'"
c.execute(sqlcmd)
user = c.fetchone()
conn.close()
if user:
return True, user
return False, "ユーザー名またはパスワードが無効です"
def process_logout():
time.sleep(1)
return gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
# Login Logic
def process_login(username, password, current_user_info_state):
username_error = validate_username(username)
password_error = validate_password(password)
if username_error:
return gr.update(value=f"{username_error}
"), False, None, None, gr.update(visible=True), gr.update(visible=False)
elif password_error:
return gr.update(value=f"{password_error}
"), False, None, None, gr.update(visible=True), gr.update(visible=False)
else:
success, result = login_user(username, password)
if success:
user_info = {
"id": result[0],
"username": result[1],
"email": result[2],
"phone": result[4],
"basic_format": result[5]
}
uid = result[5]
conn = mydb.connect(
host='www.ryhintl.com',
port='36000',
user='smairuser',
password='smairuser',
database='smair'
)
c = conn.cursor()
sqlcmd = "SELECT contents FROM gyoseki_basic_format WHERE id = "+str(uid)
c.execute(sqlcmd)
content = c.fetchone()
global basic_format
basic_format = content
conn.close()
return gr.update(value=""), True, username, user_info, gr.update(visible=False), gr.update(visible=True), gr.update(visible=True), gr.update(visible=False)
#return gr.update(value=""), True, username, user_info, gr.update(visible=False), gr.update(visible=True)
else:
#return gr.update(visible=False), gr.update(visible=True)
return gr.update(value=f"{result}
"), False, None, None, gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), gr.update(visible=True)
#return gr.update(value=f"{result}
"), False, None, None, gr.update(visible=True), gr.update(visible=False)
def get_grounded_response(prompt1, prompt2, prompt3):
"""
Calls the Gemini API with the given prompt, applies grounding,
and returns the response text with added citations.
"""
try:
final_prompt = f"{prompt1}と{prompt2}と{prompt3}を元に、プロジェクト毎に評価を含めて最終評価レポートを作成してください。"
# Make the request to the Gemini model
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=final_prompt,
#config=config,
)
return response.text
except Exception as e:
return f"An error occurred: {e}"
def set_eval_kijyun(kijun):
global eval_kijyun
eval_kijyun = kijun
return "基準が設定されました"
def prompt_change(prompt):
if len(prompt) > 0:
return gr.update(visible=True)
else:
return gr.update(visible=False)
def show_tab_1():
return gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)
def show_tab_2():
return gr.update(visible=False), gr.update(visible=True), gr.update(visible=False)
def show_tab_3():
return gr.update(visible=False), gr.update(visible=False), gr.update(visible=True)
with gr.Blocks(title="パフォーマンス評価", theme=gr.themes.Soft(), 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;}
.gradio-container {
background-color: #f8f9fa;
/*width: 100%;
height: 100%;
background-image: url('https://images.unsplash.com/photo-1527181152855-fc03fc7949c8?auto=format&w=1000&dpr=2');
background-size: cover;
background-repeat: no-repeat;
background-position: center center;*/
}
.main {
background-color: #f8f9fa;
}
.logo-container {
position: absolute;
top: 1px;
left: 20px;
z-index: 1000;
}
.logo-container img {
height: 30px;
width: auto;
}
.title {
font-size: 1.5rem;
font-weight: 700;
color: #2c3e50;
text-align: center;
margin-bottom: 1.5rem;
}
.subtitle {
font-size: 0.1rem;
color: #7f8c8d;
text-align: center;
margin-bottom: 2rem;
}
.rcard {
background: #000055;
border-radius: 15px;
padding: 2rem;
box-shadow: 0 10px 20px rgba(0,0,0,0.1);
margin-bottom: 1rem;
height: 650px;
overflow: hidden;
}
.card {
background: white;
border-radius: 15px;
padding: 2rem;
box-shadow: 0 10px 20px rgba(0,0,0,0.1);
margin-bottom: 1rem;
}
.success-message {
color: #27ae60;
text-align: center;
margin-top: 1rem;
}
.error-message {
color: #e74c3c;
text-align: center;
margin-top: 1rem;
}
.footer {
text-align: center;
margin-top: 1rem;
color: #95a5a6;
font-size: 0.8rem;
}
.avatar {
width: 50px;
height: 50px;
border-radius: 50%;
margin: 0 auto 1rem auto;
display: block;
object-fit: cover;
border: 3px solid #4a90e2;
}
.avatar:hover {
transform: scale(1.2);
border: 3px solid #4a90e2;
}
.gr-button {
width: 100%;
border-radius: 10px;
padding: 10px;
background-color: #4a90e2;
color: white;
border: none;
font-weight: 500;
transition: all 0.3s;
}
.gr-button:hover {
background-color: #357abd;
color: lightyellow;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.gr-textinput, .gr-textbox {
border-radius: 10px;
padding: 10px;
border: 1px solid #ced4da;
}
.my-custom-button {
background-color: transparent !important; /* 緑色 */
color: black !important;
padding: 10px 20px !important;
border: solid thin black !important;
border-radius: 5px !important;
cursor: pointer !important;
font-size: 16px !important;
width: 100%;
transition: background-color 0.3s ease !important;
}
.my-custom-button:hover {
background-color: #fff5ee !important; /* ホバー時の色 */
}
""") as demo:
gr.HTML('')
# State variables
current_username = gr.State(None)
current_user_info = gr.State(None)
logged_in_state = gr.State(False)
with gr.Sidebar(position="left", open=True):
gr.Markdown("©️ Performance Review 2025")
signin = gr.Button("サインイン", visible=True, elem_classes=["my-custom-button"], icon="https://img.icons8.com/fluency/48/azure-1.png")
query = gr.Button("パフォーマンス評価", visible=False, elem_classes=["my-custom-button"], icon="https://img.icons8.com/fluency/48/orthogonal-view.png")
smry = gr.Button("評価基準設定", visible=False, elem_classes=["my-custom-button"], icon="https://img.icons8.com/3d-fluency/48/domain.png")
#with gr.Tabs() as tabs:
# Set the first tab to be visible by default
with gr.Column("タブ1", visible=False, elem_classes="card") as b1:
signup_btn = gr.Button("サインアップ", elem_classes=["my-custom-button"], icon="https://img.icons8.com/color/48/000000/google-logo.png")
login_username = gr.Textbox(label="ユーザー名", placeholder="ユーザー名を入力してください", value="fmuser1")
login_password = gr.Textbox(label="パスワード", type="password", placeholder="パスワードを入力してください", value="fmuser1@Mails")
login_status = gr.Markdown("")
login_btn = gr.Button("サインイン")
output_html = gr.HTML()
signup_btn.click(
fn=open_signup_window,
inputs=[],
outputs=[output_html]
)
login_btn.click(
process_login,
inputs=[login_username, login_password, current_user_info],
outputs=[login_status, logged_in_state, current_username, current_user_info, signin, query, smry, b1]
)
with gr.Column("タブ2", visible=False) as b2:
with gr.TabItem("パフォーマンス評価"):
logout_btn = gr.Button("ログアウト")
with gr.Row(visible=True) as filecomp:
gr.Textbox(label="サンプル", show_copy_button=True, lines=10, value="""
パフォーマンスレポート
被評価者氏名 田中 太郎
職位/役職 シニアアソシエイト
評価期間: 2024年4月1日 〜 2025年3月31日
評価者名前 吉岡晴彦
1. 業績評価の概要(総合評価:A)
田中氏は、期間中、極めて優れた業績を達成しました。特に「コニカコスト削減プロジェクト」では、契約目標であるコスト10%削減に対し、12%の削減プランを策定し、初年度実行目標を達成しました。この成功において、田中氏が主導したシミュレーションモデルは、迅速かつ正確であり、定量的目標を上回る結果に決定的に貢献したと評価されています(A+評価)。
クライアント満足度も非常に高く、「非常に満足」の評価を得て後続案件の受注に貢献しましたが、部門間の利害調整が難航した際、一歩踏み込んだファシリテーションの機会を逸した点が、今後の改善点として挙げられています。また、ファームへの貢献としては、新メンバー2名へのOJT実施や、社内勉強会での積極的なナレッジ共有が高く評価されています。
2. 能力評価の概要(総合評価:A+)
田中氏の能力評価は「A+」であり、その核となる「問題解決・論理的思考力」は極めて高いと評価されています。
「信越化学新規事業戦略策定プロジェクト」では、市場データから**「参入すべきではない理由」を検証するクリティカルな仮説**を提示し、戦略の精度を向上させました。専門知識(特にデータ分析ツール:Python/Rの活用能力)についてもファーム内トップクラスとされています。
一方で、さらなる成長のためには、複雑な分析結果を経営層だけでなく非専門家(現場スタッフ)に対し、**シンプルな「メッセージ」や「必要性・メリット」として伝える際の「大胆さと示唆の鋭さ」**を磨くことが求められています。
3. 行動評価の概要(総合評価:A)
リーダーシップと責任感においても、田中氏は高い評価を得ています。「信越化学新規事業戦略策策定プロジェクト」の終盤でチームの士気が低下した際、自発的なミーティングを企画してタスクを再分配し、チームを再結集させたことは、その影響力を示す具体的な事例です。
また、担当タスクの納期遅延やミスの発生はゼロであり、極めて高い実行力と責任感を証明しています。
主要な改善点として、自身のタスク遂行能力の高さゆえに、チームメンバーへの「委譲(任せる)」スキルが不足している点が指摘されました。次期は、仕事を適切に分散させ、チーム全体の生産性を向上させるためのリーダーシップの強化が必要です。
4. 総括と次期への焦点
期間中の最も優れていた点(Kudos)
田中氏は、マネージャーへの昇進に必要な問題解決能力と専門知識を完全に満たしていると評価されています。高い分析力と責任感は、ファームの信頼構築に不可欠な要素です。
成長のための主要な改善点(Focus Area)
次期は、単なるタスク遂行者から**「プロジェクトのオーナー」へと意識をシフトすること**が最重要課題です。
具体的には、クライアントやチームに対して明確な方向性を提示するファシリテーション力と、自らのタスクを適切に任せて成果を出す「委譲と育成」のリーダーシップを重点的に強化する必要があります。""")
user_input = gr.Textbox(
label="パフォーマンス:",
info="パフォーマンス評価を入力してください。",
lines=10
)
user_score = gr.Textbox(
label="評価者の総合評価:",
info="評価者の総合評価を入力してください。",
lines=1
)
user_userid = gr.Textbox(
label="評価者のID:",
info="評価者のIDを入力してください。",
lines=1
)
# Output component to display the model's response
output_text = gr.HTML(
label="パフォーマンス評価:",
value='結果
'
)
output_file = gr.HTML(
label="パフォーマンス評価ファイル"
)
'''output_html = gr.File(
label="パフォーマンス評価ファイル"
)'''
# Button to trigger the API call
submit_button = gr.Button("生成", visible=False)
user_input.change(fn=change_input, inputs=[user_input], outputs=[submit_button])
# Connect the components: when the button is clicked,
# the generate_response function is called with the user_input,
# and the result is displayed in the output_text box.
submit_button.click(
fn=generate_review,
inputs=[user_input, user_score, user_userid],
outputs=[output_text, output_file]
#outputs=[output_text, output_html]
)
with gr.Column("タブ3", visible=False) as b3:
with gr.TabItem("パフォーマンス評価基準作成"):
kijun_input = gr.Textbox(
label="御社のパフォーマンス評価基準",
lines=10,
value="""
評価会議のための質問事項(評価ガイド)
1. イントロダクションと全体像の確認対象質問・論点目的評価者「この評価レポートの意図は、過去を裁くことではなく、今後の成長を最大化することです。まず、レポートの全体的な評価について、あなたの最初の感想を教えてください。」建設的な雰囲気を作り、自己評価と他者評価のギャップを認識させる。評価者「期間を通じて、あなたが設定していた最も重要な目標は何でしたか?その目標達成度はどの程度ですか?」評価の焦点を合わせ、本人の認識を明確にする。
2. 業績評価に関する質問(成果の深掘り)対象質問・論点目的コンサルタント「期間中、あなたが最も価値を提供できたと実感しているプロジェクト(または成果物)はどれですか?具体的にクライアントにどのようなインパクトを与えましたか?」本人が誇る成果を確認し、具体的な事例を掘り下げる。評価者「『プロジェクト〇〇』での目標達成度は高いと評価しましたが、その成功の**最も大きな要因(KFS)**は何だったと考えますか?」成功の再現性を高めるための要因分析を促す。評価者「逆に、目標を達成できなかった、あるいは難航したプロジェクトについて、主要なボトルネックは何でしたか?それはコントロール可能な要因とコントロール不能な要因のどちらでしたか?」失敗からの学びを引き出し、客観的な状況分析力を評価する。評価者「あなたの提案資料は非常に論理的でしたが、**『伝達力』**の項目で改善点があると評価したのは、どのような場面(例:クライアントとの交渉、経営層へのプレゼン)でのことですか?」定性的な評価について、具体的な場面(コンテキスト)を示してフィードバックする。
3. 行動評価に関する質問(プロセスとプロフェッショナリズム)対象質問・論点目的評価者「『プロジェクトA』の緊迫した状況下で、あなたはチームに対してどのようなリーダーシップを発揮しましたか?具体的な行動を教えてください。」プレッシャー下での行動やチームへの影響力を評価する。コンサルタント「期間中の業務プロセスを振り返って、より良い結果を出すために一つだけ変えられるとしたら、どの時点のどの行動を変えますか?」振り返りから改善につなげる内省力と、行動の重要性を理解しているかを評価する。評価者「クライアントとのコミュニケーションにおいて、特に信頼関係を深めるために意識的に行っていたことは何ですか?結果としてどうなりましたか?」クライアントリレーション構築における意識的な努力と、その結果を評価する。
4. 総括とネクストステップ(キャリア開発)対象質問・論点目的評価者「総合的に見て、次の職位(例:マネージャー)へ昇進するために、現時点で最も不足していると判断するスキルや行動は何ですか? 具体的な基準に照らして説明します。」次の職位への期待値(卒業要件)を明確に伝え、ギャップを埋めるための目標設定につなげる。コンサルタント「この評価レビューを通じて、他に懸念点や疑問点はありますか?私からのフィードバックに納得できない点があれば、ぜひ教えてください。」相互理解を深め、オープンな関係を維持したまま会議を終える。
"""
)
set_button = gr.Button("パフォーマンス評価基準", variant="primary",visible=True)
set_button.click(
fn=set_eval_kijyun,
inputs=[kijun_input],
outputs=[kijun_input]
)
user_input1 = gr.Textbox(
label="評価プロファイル",
info="""
被評価者氏名 田中 太郎
職位/役職 シニアアソシエイト
評価期間 2024年4月1日 〜 2025年3月31日
評価者名前 吉岡晴彦
評価日 2025年12月2日
""",
lines=5,
interactive=True # Allow user to type
)
user_input2 = gr.Textbox(
label="評価1",
info="""
コニカコスト削減プロジェクト」の成果と次期マネージャーへの課題
田中さんは、本プロジェクトにおいて、シニアアソシエイトとして期待される水準を大きく上回る成果を達成しました。特に、コスト削減の契約目標(10%)を上回る12%の削減プランの策定に決定的に貢献した、迅速かつ正確なシミュレーションモデル構築能力は特筆すべき点です。これは、田中さんが持つ高度な分析専門知識と、プロジェクト遂行における極めて高い実行力・責任感の証左であり、「担当タスクの納期遅延やミスの発生がゼロ」という事実からも裏付けられています。業績評価における「A+」は、この定量的な成果と、クライアントからの「非常に満足」という高い評価に基づいてい ます。
一方で、次期マネージャーへのプロモーションを視野に入れる上で、プロジェクトのオーナーシップの面で改善すべき点が浮き彫りになりました。クライアント満足度が高く、個別ステークホルダーへの配慮は優れているものの、「部門間の利害調整が難航した際、一歩踏み込んだファシリテーションの機会を逸した」という自己評価は、まさにこの課題を指し示しています。シニアアソシエイトは「タスクの最高責任者」ですが、マネージャーは「プロジェクト全体の結論と方向性の最高責任者」です。今後は、困難な状況で明確な「Go/No-Go」を提示し、コンセンサスを形成する「大胆なファシリテーション力」を重点的に磨く必要があります。これは、単なる調整役ではなく、プロジェクトを成功に導く推進力に直結します。""",
lines=5,
interactive=True # Allow user to type
)
user_input3 = gr.Textbox(
label="評価2",
info="""
信越化学新規事業戦略策定プロジェクト」における知見の深化とリーダーシップの強化
田中さんは、信越化学新規事業戦略策定プロジェクト」では、問題解決能力と論理的思考力がファーム内でトップクラスであることを改めて証明しました。特に、「一般的な推奨とは異なる**『参入すべきではない理由』を検証するクリティカルな仮説**」を提示したことは、膨大なデータに溺れることなく、真の戦略的な示唆を抽出する田中さんの本質を見抜く力を示しています。技術的な専門知識、特にPython/Rを用いたデータ分析能力は、チームの生産性を大きく押し上げました。
しかし、この高度な専門性を、より広いビジネスインパクトに結びつけるための**「伝達力」と「委譲能力」の強化が求められます。複雑な分析結果を、経営層や非専門家である現場スタッフに対し、「なぜ、今これをやるべきか」というシンプルな「メッセージ」と「示唆の鋭さ」をもって伝えきる能力は、田中さんが今後、大規模プロジェクトを牽引するために不可欠なスキルです。高度な分析結果を「翻訳」し、組織全体を動かす「影響力」**を意識してほしい。
また、リーダーシップの面では、士気の低下したチームを自発的に再結集させた功績は素晴らしいものの、「自身のタスク遂行能力の高さゆえに、チームメンバーへの**『委譲(任せる)スキルが不足している』」という指摘は重要です。マネージャーは、自分一人で成果を出すのではなく、チーム全体のパフォーマンスを最大化することが役割です。次期は、タスクを任せることでメンバーを成長させ、プロジェクトの生産性を複利的に高める「育成と委譲のリーダーシップ」**を意識的に実践していくことが、最重要課題となります。""",
lines=5,
interactive=True # Allow user to type
)
output_text = gr.Textbox(
label="プレ・レビュー・レポート",
lines=10,
show_copy_button=True,
interactive=False # Allow user to type
)
pre_button = gr.Button("プレ・レビュー・レポートを作成")
pre_button.click(
fn=get_grounded_response,
inputs=[user_input1, user_input2, user_input3],
outputs=output_text
)
signin.click(show_tab_1, inputs=None, outputs=[b1, b2, b3])
query.click(show_tab_2, inputs=None, outputs=[b1, b2, b3])
smry.click(show_tab_3, inputs=None, outputs=[b1, b2, b3])
logout_btn.click(
process_logout,
inputs=[],
outputs=[signin,query,smry,b2]
)
demo.launch(favicon_path="favicon.ico")
自己評価: 契約目標(コスト10%削減)に対し、12%の削減プランを策定し、初年度実行目標(5%削減)を達成。データ収集と経営層向け報告書作成を主導。