File size: 6,972 Bytes
c1466e0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90a4b9c
 
f0623c6
 
 
 
c1466e0
 
 
 
 
 
 
 
 
 
 
 
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
import gradio as gr
import random
import time
import csv
import os
import pandas as pd
from openai import OpenAI
import numpy as np
import ast
import json


# ユーザーの諸々の情報やプロンプトを受け取り返答する
def search_teacher(job_type, job_start_dates, tool_function_arguments):
    user_request = ', '.join(list(tool_function_arguments.values())[:-2])
    user_message_embedded_vector = \
        client.embeddings.create(input=[user_request.replace("\n", " ")], model='text-embedding-3-small').data[
            0].embedding

    data = pd.read_csv(os.environ['DATA_PATH'])

    # job_type の日本語を英語に変換
    if job_type == '常勤':
        job_type = 'full time'
    elif job_type == '非常勤':
        job_type = 'part time'

    # job_start_dates の日本語を英語に変換
    job_start_date_translation = {
        '今年度': 'This Year',
        '来年度': 'Next Year',
        '来来年度': 'Year After Next'
    }
    # job_start_dates が文字列の場合リストに変換(単一選択の場合を考慮)
    if isinstance(job_start_dates, str):
        job_start_dates = [job_start_dates]
    # 英語に変換
    job_start_dates = [job_start_date_translation.get(date, date) for date in job_start_dates]

    # job_type と job_start_dates でフィルタリング
    filtered_data = data[(data['job_type'] == job_type) & (data['job_start_date'].isin(job_start_dates))].copy()

    result = []

    for index, row in filtered_data.iterrows():
        teacher_embedded_vector = ast.literal_eval(row['embedding'])

        similarity = np.dot(user_message_embedded_vector, teacher_embedded_vector) / (
                np.linalg.norm(user_message_embedded_vector) * np.linalg.norm(teacher_embedded_vector))

        if len(result) < 3:
            result.append((index, similarity))
            result.sort(key=lambda x: x[1], reverse=True)
        else:
            if similarity > result[-1][1]:
                result[-1] = (index, similarity)
                result.sort(key=lambda x: x[1], reverse=True)

    formatted_result = []
    for index, similarity in result:
        name = filtered_data.loc[index, 'name']
        temp = f"{name}: {similarity}"
        formatted_result.append(temp)

    return ', '.join(formatted_result)


def openai_api(job_type, job_start_dates, history):
    # GPTにユーザーの入力を送信
    message = client.beta.threads.messages.create(
        thread_id=thread.id,
        role="user",
        content=history[-1][0]
    )

    # 送信した入力を実行
    run = client.beta.threads.runs.create(
        thread_id=thread.id,
        assistant_id=assistant.id,
    )

    while True:
        run = client.beta.threads.runs.retrieve(
            thread_id=thread.id,
            run_id=run.id
        )
        if run.status == 'completed':
            break
        elif run.status == 'requires_action':
            tool_id = run.required_action.submit_tool_outputs.tool_calls[0].id
            tool_function_arguments = json.loads(
                run.required_action.submit_tool_outputs.tool_calls[0].function.arguments)

            tool_function_output = search_teacher(job_type, job_start_dates, tool_function_arguments)

            run = client.beta.threads.runs.submit_tool_outputs(
                thread_id=thread.id,
                run_id=run.id,
                tool_outputs=[
                    {
                        "tool_call_id": tool_id,
                        "output": tool_function_output,
                    }
                ]
            )
            time.sleep(3)

        time.sleep(0.5)

    messages = client.beta.threads.messages.list(
        thread_id=thread.id,
        order="asc"
    )

    return messages.data[-1].content[0].text.value


def user(user_job_type, user_job_start_date, user_message, history):
    return None, history + [[user_message, None]]


def bot(job_type, job_start_date, history):
    prompt = ""
    # apiを叩くためにデータを加工するなりする
    for chat in history[:-1]:
        prompt += '"' + chat[0] + '", "' + chat[1] + '"'

    bot_message = openai_api(job_type, job_start_date, history)

    history[-1][1] = ""
    for character in bot_message:
        history[-1][1] += character
        time.sleep(0.01)

        yield history


with gr.Blocks(theme=gr.themes.Soft()) as demo:
    global assistant
    global thread
    global client

    client = OpenAI(max_retries=5)

    assistant = client.beta.assistants.create(
        name='connpath_demo',
        instructions=os.environ['INSTRUCTIONS'],
        model="gpt-4-0125-preview",
        tools=[{
            "type": "function",
            "function": {
                "name": "connpath_demo_gpt",
                "description": "検索を支援する",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "educational_goals": {"type": "string", "description": "教育の目的"},
                        "student_profile": {"type": "string", "description": "対象のプロフィール"},
                        "required_skills_experience": {"type": "string", "description": "求められるスキル"},
                        "teaching_method_environment": {"type": "string", "description": "教育する環境"},
                        "evaluation_feedback": {"type": "string", "description": "教育の評価方法"}
                    },
                    "required": ["educational_goals", "student_profile", "required_skills_experience",
                                 "teaching_method_environment", "evaluation_feedback"]
                }
            }
        }]
    )

    thread = client.beta.threads.create()

    # これがuser_job_typeを保持 (str型)
    job_type = gr.Radio(["常勤", "非常勤"],
                        label="Job Type",
                        info="探している雇用形態について")

    # これがuser_job_start_dateを保持 (list型)
    job_start_date = gr.CheckboxGroup(["今年度", "来年度", "来来年度"],
                                      label="Start Date",
                                      info="探している就業時期について")

    # これがuser_messageを保持
    msg = gr.Textbox(label="input message",
                     info="課題について教えてください(例:国語の先生を探しています)")

    # これがhistoryを保持
    chatbot = gr.Chatbot(show_copy_button=True)

    clear = gr.Button("clear history")

    msg.submit(user,
               [job_type, job_start_date, msg, chatbot],
               [msg, chatbot],
               queue=True
               ).then(bot, [job_type, job_start_date, chatbot], chatbot)
    clear.click(lambda: None, None, chatbot, queue=False)

if __name__ == "__main__":
    demo.queue()
    demo.launch(auth=(os.environ['USER_NAME'], os.environ['PASSWORD']))