File size: 16,451 Bytes
49f62f9
 
 
 
 
0af68fe
 
 
c01bc87
debcd4c
49f62f9
0af68fe
edab815
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49f62f9
edab815
 
 
 
49f62f9
 
edab815
 
 
 
 
 
 
 
 
 
49f62f9
 
 
 
edab815
 
 
 
49f62f9
 
 
 
 
edab815
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
debcd4c
49f62f9
edab815
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
debcd4c
edab815
 
 
 
 
49f62f9
edab815
 
49f62f9
edab815
 
 
 
 
 
 
49f62f9
 
 
 
 
c01bc87
edab815
 
49f62f9
edab815
49f62f9
 
edab815
49f62f9
 
 
edab815
 
49f62f9
 
edab815
 
49f62f9
 
edab815
 
49f62f9
 
edab815
 
49f62f9
 
edab815
 
49f62f9
 
edab815
 
49f62f9
 
edab815
 
49f62f9
 
edab815
 
49f62f9
 
 
 
 
 
 
 
 
edab815
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49f62f9
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
import gradio as gr
import cohere
import os
import json
from dotenv import load_dotenv
#from qdrant_client import QdrantClient
#from qdrant_client.models import Filter, FieldCondition, MatchValue
#import json

load_dotenv(verbose=True)

#client = QdrantClient(url="http://localhost:6333")

def get_scores_for_users(userids):
    try:
        userids_list = userids.split(",")  # Split user IDs into a list
        result_messages = []  # Store results for each userid

        for userid in userids_list:
            userid = userid.strip()  # Clean up whitespace around user IDs

            # Build filter to query points for the specific userid
            filter_condition = {
                "must": [
                    {
                        "key": "userid",
                        "match": {"value": userid}
                    }
                ]
            }

            # Query Qdrant for points matching the userid
            results = client.scroll(
                collection_name="skill_scores",
                limit=6,  # Adjust based on your needs
                with_payload=True  # Include payloads for manual filtering
            )

            filtered_results = [
                point.payload["score"] for point in results[0]
                if point.payload.get("userid") == userid
            ]

            #result_messages.append(f'{{"{userid}": {filtered_results}}}')
            result_messages.append(f'{{"userid":"{userid}","score": {filtered_results}}}')

            # Join result_messages into a single JSON-compatible string
            json_data = "[" + ",".join(result_messages) + "]"

            # Parse the JSON string into Python data
            parsed_data = json.loads(json_data)

            # Optional: Print or process parsed data
            print(parsed_data)

            # useridの取り出し
            userid = parsed_data[0]["userid"]
            print(f"User ID: {userid}")

            # scoreの各項目を取り出し
            scores = parsed_data[0]["score"]
            print(f"Score: {scores}")

        #return "\n".join(result_messages)  # Return results for all user IDs
        return userid,scores
    except Exception as e:
        return f"Error occurred while retrieving scores: {str(e)}"

def update_lang(lang):
    if len(lang) == 0:
        return gr.update(value="Pythonが得意。スクリプト作成やデータ分析、機械学習まで幅広く活用している。")
    else:
        return gr.update(value=lang)
    
def update_debug(debug):
    if len(debug) == 0:
        return gr.update(value="よく使うのはpdb(Python Debugger)やVS Codeのデバッガ機能。エラー箇所を細かくチェックするのが好き。")
    else:
        return gr.update(value=debug)
    
def update_recent_problem(recent_problem):
    if len(recent_problem) == 0:
        return gr.update(value="例えば、APIの連携でエラーが続発する問題があったとき、レスポンスをしっかりロギングしてパターンを分析、結果的にリクエストヘッダーを微調整して解決できた。")
    else:
        return gr.update(value=recent_problem)
    
def update_project_approach(project_approach):
    if len(project_approach) == 0:
        return gr.update(value="チーム内でブレインストーミングしてアイデアを出し合い、最良の解決策を選択するのが常套手段だと思っている。")
    else:
        return gr.update(value=project_approach)
    
def update_project_scale(project_scale):
    if len(project_scale) == 0:
        return gr.update(value="1人で取り組むものから、数十人規模の開発チームでクラウドシステム構築などをした経験もある。")
    else:
        return gr.update(value=project_scale)
    
def update_team_role (team_role):
    if len(team_role ) == 0:
        return gr.update(value="主にテクニカルリーダーとして、設計からレビューまでを担当。時には新人教育も。")
    else:
        return gr.update(value=team_role)
    
def update_learning_methods(learning_methods):
    if len(learning_methods) == 0:
        return gr.update(value="実際に手を動かして試すのが一番。Tutorialやドキュメントを読みながらプロトタイプを作成。")
    else:
        return gr.update(value=learning_methods)
    
def update_recent_learning(recent_learning):
    if len(recent_learning) == 0:
        return gr.update(value="最近は生成AIのモデルチューニング方法について学んだよ。これでさらに便利なプロジェクトが作れる。")
    else:
        return gr.update(value=recent_learning)



# スコアを抽出する関数
def post_scores(state,email):
    if len(email) == 0:
        return "検査結果がありません!"
    else:
        state['final_email'] = email
        state['final_comment'] = """{
        "技術的な理解": 9,
        "問題解決能力": 8.5,
        "実務経験": 8,
        "学習意欲": 9,
        "ソフトスキル": 8.5,
        "合計スコア": 8.6
        }"""

        co = cohere.ClientV2(api_key=os.environ.get("COHERE_API_KEY"))
        res = co.chat(
            model="command-a-03-2025",
            messages=[
                {
                    "role": "user",
                    "content": f"これは{state['final_email']}さんのデータです。{state['final_comment']}を評価してください。生成された結果に基づいて{state['final_email']}さんに送るスカウト提案メールも作ってください。答えは、必ず、評価結果とメールの本文を日本語で返してください。",
                }
            ],
        )
        data = res.message.content[0].text
        return data

# スコアを抽出する関数
def extract_scores(state):
    if len(state["final_score"]) == 0:
        return "検査結果がありません!"
    else:
        co = cohere.ClientV2(api_key=os.environ.get("COHERE_API_KEY"))
        res = co.chat(
            model="command-a-03-2025",
            messages=[
                {
                    "role": "user",
                    "content": f"これは{state['final_email']}さんのデータです。{state['final_comment']}を評価してください。生成された結果に基づいて{state['final_email']}さんに送るスカウト提案メールも作ってください。答えは、必ず、評価結果とメールの本文を日本語で返してください。",
                }
            ],
        )
        data = res.message.content[0].text
        return data
        
# 簡易評価の関数
def evaluate_responses(state, email, programming, debugging, problem, problem_solving, project_experience, role, learning, learnt_skills):
    state["final_email"] = email

    if (email != "" and programming != "" and debugging != "" and problem != "" and problem_solving != "" and project_experience != "" and role != "" and learning != "" and learnt_skills != ""):
        # レコード作成
        records = f"""
        ✨プログラミング言語について: {programming}
        ✨デバッグ方法について: {debugging}
        ✨最近解決した技術的な課題: {problem}
        ✨プロジェクト問題解決方法について: {problem_solving}
        ✨プロジェクト経験について: {project_experience}
        ✨チームでの役割について: {role}
        ✨新しい技術への学習意欲について: {learning}
        ✨最近学んだ技術や知識について: {learnt_skills}
        """
        co = cohere.ClientV2(api_key=os.environ.get("COHERE_API_KEY"))
        res = co.chat(
            model="command-a-03-2025",
            messages=[
                {
                    "role": "user",
                    "content": f"""
                    {records}を「基準」に基づいて各項目の合計スコアを10段階で割り振って評価してください。答えは、必ず、「形式」で合計スコアのみを返してください。
                    「基準」=価基準とポイント配分
                    技術的な理解 (30%): 例えばプログラミング言語の知識やデバッグ能力を考慮。コード品質や問題解決能力が評価対象。
                    問題解決能力 (25%): 技術的課題への対応スキルやアプローチ方法をチェック。現実的かつ効率的な解決策を出せるかどうか。
                    実務経験 (20%): 過去のプロジェクト経験の内容や規模。実際の成果や役割が評価される。
                    学習意欲 (15%): 新しい技術をどれだけ積極的に学び、適応しているか。最近学んだ知識がアピールポイント!
                    ソフトスキル (10%): チームワークやコミュニケーション能力。エンジニアの柔軟性や協力姿勢を評価。
                    「形式」= {{
                    "技術的な理解": 9,
                    "問題解決能力": 8.5,
                    "実務経験": 8,
                    "学習意欲": 9.5,
                    "ソフトスキル": 8.5,
                    "合計スコア": 8.63,
                    "スキルレベル": "Expert",
                    "説明": "技術力や問題解決能力、学習意欲が高くバランスの良いスキルセットを持っている。"
                    }}
                    """,
                }
            ],
        )

        cleaned_string = res.message.content[0].text.replace("```json", "").replace("```", "").strip()
    
        data = json.loads(cleaned_string)
        #data = json.loads(res.message.content[0].text)
        comments = "\n".join([f"{key}: {value}" for key, value in data.items()])
        scores = [f"{key}: {value}" for key, value in data.items()]
        print("db-scores:",scores)

        state["final_comment"] = comments
        state["final_score"] = scores

        return records, comments
    else:
        return "入力が正しくありません。","None"


# Gradio Blocksの構築
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;}", theme=gr.themes.Glass(), title="エンジニア・スキル評価") as inquery:
    state = gr.State({
        "final_email": "",
        "final_comment": "",
        "final_score": [],
    })

    gr.HTML('<div id="header"><span>🧑‍🏫👩‍🏫 エンジニア・スキル評価</span><img id="logo" src="https://www.ryhintl.com/images/ryhlogo/ryhlogo.png" width="64" height="64" alt="Logo"></div>')
    gr.Markdown("エンジニア・スキルを簡易評価するアプリです!")

    with gr.Tab("エンジニア・スキル評価質問フォーム"):
        # 入力フィールド
        with gr.Row():
            email = gr.Textbox(label="電子メールを入力してください。", info="your mail address")
            
        with gr.Row():
            lang = gr.Textbox(label="普段使用しているプログラミング言語は何ですか?、尚、経験年数を教えてください。", 
                          info="Pythonが得意。スクリプト作成やデータ分析、機械学習まで幅広く活用している。", value="")
            lang.submit(fn=update_lang,inputs=[lang],outputs=[lang])
        with gr.Row():
            debug_tools = gr.Textbox(label="コードのデバッグ方法やツールについて教えてください。", 
                                 info="よく使うのはpdb(Python Debugger)やVS Codeのデバッガ機能。エラー箇所を細かくチェックするのが好き。")
            debug_tools.submit(fn=update_debug,inputs=[debug_tools],outputs=[debug_tools])
        with gr.Row():
            recent_problem = gr.Textbox(label="最近解決した技術的な課題を教えてください。どのようにアプローチしましたか?", 
                                    info="例えば、APIの連携でエラーが続発する問題があったとき、レスポンスをしっかりロギングしてパターンを分析、結果的にリクエストヘッダーを微調整して解決できた。")
            recent_problem.submit(fn=update_recent_problem,inputs=[recent_problem],outputs=[recent_problem])
        with gr.Row():
            project_approach = gr.Textbox(label="複雑なプロジェクトで課題が発生した場合、どう対処しますか?", 
                                      info="チーム内でブレインストーミングしてアイデアを出し合い、最良の解決策を選択するのが常套手段だと思っている。")
            project_approach.submit(fn=update_project_approach,inputs=[project_approach],outputs=[project_approach])
        with gr.Row():
            project_scale = gr.Textbox(label="過去に関わったプロジェクトの規模や内容を教えてください。", 
                                   info="1人で取り組むものから、数十人規模の開発チームでクラウドシステム構築などをした経験もある。")
            project_scale.submit(fn=update_project_scale,inputs=[project_scale],outputs=[project_scale])
        with gr.Row():
            team_role = gr.Textbox(label="チームでどのような役割を果たしましたか?", 
                               info="主にテクニカルリーダーとして、設計からレビューまでを担当。時には新人教育も。")
            team_role.submit(fn=update_team_role,inputs=[team_role],outputs=[team_role])
        with gr.Row():
            learning_methods = gr.Textbox(label="新しい技術を学ぶ際にどのような方法を取っていますか?", 
                                      info="実際に手を動かして試すのが一番。Tutorialやドキュメントを読みながらプロトタイプを作成。")
            learning_methods.submit(fn=update_learning_methods,inputs=[learning_methods],outputs=[learning_methods])
        with gr.Row():
            recent_learning = gr.Textbox(label="最近学んだ技術や知識は何ですか?", 
                                     info="最近は生成AIのモデルチューニング方法について学んだよ。これでさらに便利なプロジェクトが作れる。")
            recent_learning.submit(fn=update_recent_learning,inputs=[recent_learning],outputs=[recent_learning])
    
        # ボタンと出力フィールド
        with gr.Row():
            submit_btn = gr.Button("スキル評価")
        with gr.Row():
            result = gr.Textbox(label="結果", show_copy_button=True)
            score = gr.Textbox(label="スコア")
    

        submit_btn.click(fn=evaluate_responses, 
                         inputs=[state, email, lang, debug_tools, recent_problem, project_approach, 
                                 project_scale, team_role, learning_methods, recent_learning], 
                         outputs=[result, score])

    with gr.Tab("リアルタイム・アセスメント"):
        gr.Markdown("# エンジニア・スキルの簡易評価")
        gr.Markdown("質問フォームから各項目のスコアを抽出して評価します!")

        with gr.Row():
            display_button = gr.Button("簡易評価")
    
        with gr.Row():
            output = gr.Textbox(label="簡易評価", show_copy_button=True)

        # ボタンに関数を接続
        display_button.click(fn=extract_scores, inputs=[state], outputs=output)

    with gr.Tab("ポスト・アセスメント"):
        gr.Markdown("# エンジニア・スキルの簡易評価")
        gr.Markdown("質問フォームから各項目のスコアを抽出して評価します!")

        with gr.Row():
            input = gr.Textbox(label="電子メール",value="richardhuh0629@gmail.com")
            output = gr.Textbox(label="簡易評価", show_copy_button=True)

        with gr.Row():
            analyze_button = gr.Button("簡易評価")
    
        # ボタンに関数を接続
        analyze_button.click(fn=post_scores, inputs=[state,input], outputs=output)

inquery.launch()