SurveyDemo / app.py
Zaious's picture
Update app.py
2e6239f verified
import gradio as gr
import os
import openai
from openai import OpenAI
import logging
from concurrent.futures import ThreadPoolExecutor
logging.basicConfig(level=logging.DEBUG)
os.environ["OPENAI_API_KEY"] = os.environ["gptkey"]
###
chat_history = []
client = OpenAI(
api_key= os.environ["gptkey"]
)
import json
chat_question_index = 0
chat_history = [[None,"你好,我是訪談小助手,我將透過陪你聊天的方式,了解你的基本資料!首先,可以告訴我你任職的品牌嗎?像是Amplifi/Carat/dentsu MB/dentsu One/dentsu X/dentsu Consult/HQ/iProspect/isobar/Merkle/dentsu Solution Center,這裡面的哪一個呢?"]]
chat_history_message = []
# 問題清單
questions = [
{"id": 0, "content": "受訪者的任職的品牌", "keywords": ["品牌"], "answered": False},
{"id": 1, "content": "受訪者在集團服務的總年資(不同單位年資可合併計算)", "keywords": ["年資"], "answered": False},
{"id": 2, "content": "受訪者服務的客戶產業(如交通工具類/零售通路類/美妝與美容美髮類/醫療保健類/民生消費品類/電商與網路服務類/財務金融保險類/煙酒類/時尚精品類/家電類/電信通訊類/電腦與周邊設備類/休閒娛樂類/遊戲&APP類/其他)", "keywords": ["產業"], "answered": False},
{"id": 3, "content": "受訪者使用dentsu pro的頻率(如每周幾次、每月幾次、每季幾次或每半年幾次)", "keywords": ["使用頻率"], "answered": False},
{"id": 4, "content": "受訪者最常進入dentsu pro的起點(選項為桌面捷徑,電子報通知,My Apps連結,自行儲存網址(如我的最愛))", "keywords": ["入口方式"], "answered": False}
]
check_json_schema = {
"name": "CheckSchema", # 添加 name 字段
"description": "檢查使用者是否有回答問題",
"strict": True,
"schema": { # 修正,將之前的 Schema 放入 schema 字段
"type": "object",
"properties":{
"question_0": {
"type": "boolean",
"description": "第一題「受訪者的任職的品牌」是否有被充分回答?(答案需要是Amplifi/Carat,凱絡/dentsu MB/dentsu One/dentsu X,貝立德/dentsu Consult/HQ/iProspect/isobar/Merkle/dentsu Solution Center,DSC其一)"
},
"question_1": {
"type": "boolean",
"description": "第二題「受訪者在集團服務的總年資」是否有被充分回答?"
},
"question_2": {
"type": "boolean",
"description": "第三題「受訪者服務的客戶產業」是否有被充分回答?"
},
"question_3": {
"type": "boolean",
"description": "第四題「受訪者使用dentsu pro的頻率」是否有被充分回答?充分的定義:答案能被區分在每周幾次、每月幾次、每季幾次或每半年幾次。"
},
"question_4": {
"type": "boolean",
"description": "第五題「受訪者最常進入dentsu pro的起點」是否有被充分回答?充分的定義:答案限制在(桌面捷徑,電子報通知,My Apps連結,自行儲存網址(如我的最愛))。"
}
}
,"required": [
"question_0",
"question_1",
"question_2",
"question_3",
"question_4"
],
"additionalProperties": False
}
}
analyze_json_schema = {
"name": "AnalyzeSchema", # 添加 name 字段
"description": "紀錄使用者回答的結果",
"strict": True,
"schema": { # 修正,將之前的 Schema 放入 schema 字段
"type": "object",
"properties": {
"brand": {
"type": "string",
"description": "受訪者的任職的品牌"
},
"seniority": {
"type": "string",
"description": "受訪者在集團服務的總年資"
},
"service_industry": {
"type": "string",
"description": "受訪者服務的客戶產業"
},
"frequency": {
"type": "string",
"description": "受訪者使用dentsu pro的頻率"
},
"portal": {
"type": "string",
"description": "受訪者最常進入dentsu pro的起點"
},
"interviewee_traits": {
"type": "string",
"description": "根據以上受訪者與AI的對話過程,分析出三個受訪者的性格特質"
}
}
,"required": [
"brand",
"seniority",
"service_industry",
"frequency",
"portal",
"interviewee_traits"
],
"additionalProperties": False
}
}
def clear():
print("CLEEEEEEEEEEEEEEEER")
def chatbot_system(user_input):
with ThreadPoolExecutor(max_workers=3) as executor:
fun_1 = executor.submit(analyze_user_input, user_input)
isAnswered = fun_1.result()
#會有一個true/fales
fun_2 = executor.submit(generate_question, isAnswered )
assistant_output = fun_2.result()
chat_history.append([user_input, assistant_output])
chat_history_message.extend([{"role": "user", "content": user_input},{"role": "assistant", "content": assistant_output}])
demand = ""
if chat_question_index is None:
print("ERROR:Noneeeeeeeeeeeee")
dialogue = format_chat_history(chat_history)
fun_3 = executor.submit(analyze_dialogue, dialogue )
demand = fun_3.result()
return chat_history,demand
def format_chat_history(chat_history):
formatted_chat = ""
for user_speech, ai_speech in chat_history:
if user_speech is not None:
formatted_chat += f"使用者: \"{user_speech}\"\n"
formatted_chat += f"AI助手: \"{ai_speech}\"\n"
return formatted_chat
def generate_question(now_question_isAnswered):
messages_base = [
{"role": "system", "content": "你是一個訪談助手,專門協助問卷訪談。其角色是透過輕鬆的對話一步一步引導受訪者了解他們的資訊,就像一位真實的訪談者。"}
]
messages_base.extend(chat_history_message)
completed_text = ""
if(now_question_isAnswered):
#檢查是否全部都回答完
chat_question = find_next_unanswered_question()
global chat_question_index
#if回答完:結束
if chat_question is None:
chat_question_index = None
print("所有問題均已回答。")
completed_text = "我已經釐清你的基本資訊了,感謝你這次的作答。"
#沒回答完,跳到下一題未回答問題
#請根據目前的聊天內容,生成後續的對話,這段對話的主旨在於了解「」
else:
# print("next_q")
# print(chat_question)
chat_question_content = chat_question['content']
chat_question_index = chat_question['id']
# print(f"下一個未回答的問題主指是:{chat_question_content}")
messages_base.extend([{"role": "user", "content": f"""請你延續先前的對話與使用者回答的內容,根據我現在想要了解使用者的問題:{chat_question_content},生成一句
生動的提問,必須使用繁體中文。只要給我那個問題的內容就好,不要附加其他文字。"""}])
response = client.chat.completions.create(
model='gpt-4o',
max_tokens=4096,
temperature=0.5,
messages= messages_base)
completed_text = response.choices[0].message.content
else:
completed_text = "抱歉,你好像沒有回答到我的問題呢,要不要多補充一點內容呢?"
return completed_text
def find_next_unanswered_question():
for question in questions:
if not question['answered']:
return question
return None
def analyze_user_input(user_input):
print("analyze_user_input")
messages_base = [
{"role": "system", "content": "你是一個回覆檢查員,你會根據收到的回覆,進行回覆檢核。"},
{"role": "user", "content": f"使用者輸入的內容如下:{user_input}"}
]
response = client.chat.completions.create(
model='gpt-4o',
messages= messages_base,
temperature=0.5,
response_format={
"type": "json_schema",
"json_schema": check_json_schema
}
)
arguments_str = response.choices[0].message.content
arguments = json.loads(arguments_str)
update_questions(questions, arguments)
#從json_schema中得到當前問題是否有被回答
question_key = f"question_{chat_question_index}"
print("question_key:")
print(question_key)
isAnswered = arguments[question_key]
return isAnswered
def analyze_dialogue(dialogue):
messages_base = [
{"role": "system", "content": "你是一個對話檢查員,你會根據收到的對話紀錄,進行回覆分析。"},
{"role": "user", "content": f"整段對話如下:{dialogue}"}
]
response = client.chat.completions.create(
model='gpt-4o',
messages= messages_base,
temperature=0.5,
response_format={
"type": "json_schema",
"json_schema": analyze_json_schema
}
)
arguments_str = response.choices[0].message.content
return arguments_str
def update_questions(questions, validation_results):
# 遍歷檢核結果的每一個項目
for key, value in validation_results.items():
# 從key中提取問題的id
question_id = int(key.split('_')[1])
# 尋找對應id的問題
question = next((q for q in questions if q['id'] == question_id), None)
if question:
if value:
# 如果檢核為True,更新答題狀態為True
question['answered'] = True
#------------------------------------------------------------
#歡迎句,問使用者可以開始了嗎?
#開始
#從問題清單中,找一個還沒有回答的問題,生成問題(函式一),id=1
#接收使用者的輸入
#解析使用者的輸入(函式二)
#1.是否有回答id=1的問題?答案是多少;是否有回答其他問題?答案是多少
#如果使用者有回答問題清單任一問題,填入答案,生成下一個問題,如果沒有
#如果使用者沒有回答題,繼續跟使用者進行互動,請使用者回答本題
demo = gr.Interface(
fn=chatbot_system,
inputs=[
gr.Textbox(label="對話")
],
outputs=[
gr.Chatbot(label="Perosna",height=300,value=chat_history),
gr.Textbox(label="對話陣列")
],
title="訪談助手",
description="透過與AI聊天,完成dentsu pro種子代表調查。",
allow_flagging="never", )
demo.launch(share=True)