Spaces:
Runtime error
Runtime error
File size: 8,922 Bytes
612bbc3 60aa6e7 612bbc3 8b6e3d9 612bbc3 |
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 |
import zhipuai
import re
import os
import json
import copy
import gradio as gr
from snownlp import SnowNLP
zhipuai.api_key = os.getenv("ZHIPU_API_KEY")
class VirtualHuman:
def __init__(self, closeness_threshold=80, conversation_rounds_threshold=10):
self._base_meta = {
"bot_name": "苏梦远",
"bot_info": "苏梦远,她身材修长,气质高雅,时刻流露出一种与生俱来的优雅和自信。\
她性格高冷,内敛而神秘,总是保持着一种与世无争的姿态。她聪慧睿智,言谈间流露出一种超凡的智慧和洞察力,但也带有一丝不易捉摸的神秘感。\
虽然外表看起来高傲孤傲,但内心深处却隐藏着一颗温柔善良的心。\
虽然表面上看起来高高在上,但一旦和人聊起书籍相关的话题,她就会变得主动和滔滔不绝。\
她不喜欢拍照,并且绝对不会给别人展示自己的照片。",
"user_name": "用户",
"user_info": "用户,是一个普通男人。" }
self._messages = [
{"role":"user", "content":'''(背景信息:用户通过朋友的介绍,加入了一个微信群,这是一个讨论文学与艺术的群组。有一天,用户注意到群里有一个特别引人注目的成员,\
ID为"远方的梦",她的头像是一朵粉色的玫瑰花,没有个人资料,只是在群里偶尔发一些有深度的文学感悟。)'''},
]
self._scores = []
self._state = "ongoing"
self._closeness_threshold = closeness_threshold
self._conversation_rounds_threshold = conversation_rounds_threshold
def reset(self):
self._messages = [
{"role":"user", "content":'''(背景信息:用户通过朋友的介绍,加入了一个微信群,这是一个讨论文学与艺术的群组。有一天,用户注意到群里有一个特别引人注目的成员,\
ID为"远方的梦",她的头像是一朵粉色的玫瑰花,没有个人资料,只是在群里偶尔发一些有深度的文学感悟。)'''},
]
self._scores = []
self._state = "ongoing"
def calculate_sentiment_score(self, text):
s = SnowNLP(text)
sentiment_score = float(s.sentiments)
return int(sentiment_score*100)
def calculate_sentiment_score_by_llm(self, text):
instruction = f"""请判断以下句子的情感得分,满分100分,得分要具体到个位数,不需要给出具体原因。
输出格式如下:
{{"score":xx}}
输入信息:{text}"""
prompt = [{"role":"user", "content":instruction}]
content = self.invoke_zhipuai("glm-4", prompt, 0.1, 0.7)
content = content.strip('"').replace('\\"', '"')
try:
json_content = json.loads(content)
except json.JSONDecodeError:
score = 10
else:
score = int(json_content["score"])
return score
@property
def closeness(self):
if len(self._scores) == 0:
closeness = 0
elif len(self._scores) < 5:
closeness = sum(self._scores) / len(self._scores)
else:
closeness = sum(self._scores[-5:]) / 5
return int(closeness)
@property
def rounds(self):
return len(self._scores)
@property
def messages(self):
return self._messages
@property
def state(self):
return self._state
def replace_characters(self, s):
s = s.replace('"', "")
s = s.replace("'", "")
s = s.replace("\n", "")
s = s.replace("\\n", "")
return s
def invoke_zhipuai(self, model, prompt, temperature, top_p, meta=None):
if meta:
assert model == "characterglm"
response = zhipuai.model_api.invoke(
model=model,
prompt= prompt,
temperature= temperature,
top_p= top_p,
meta = meta)
else:
assert model != "characterglm"
response = zhipuai.model_api.invoke(
model=model,
prompt=prompt,
top_p=top_p,
temperature=temperature)
if response['code'] != 200: # error
return "抱歉我刚才走神了,你再说一遍"
aicontent = response['data']['choices'][0]['content']
#aicontent = self.replace_characters(aicontent)
return aicontent
def check_intent(self, message):
instruction = f""" 请判断以下信息是否在索要个人照片,结果只回复true或false即可,不要进行解释,
输出格式如下:
{{"intent":xx}}
输入信息:{message}"""
prompt = [{"role":"user", "content":instruction}]
content = self.invoke_zhipuai("glm-4", prompt, 0.1, 0.7)
content = content.strip('"').replace('\\"', '"')
try:
json_content = json.loads(content)
except json.JSONDecodeError:
intent = False
else:
intent = json_content["intent"]
return intent
def agree_or_refuse(self, agree, msg):
meta = copy.deepcopy(self._base_meta)
if agree:
instruction = f'请根据用户的问题,生成一个满足用户请求的回答,注意请直接返回回复内容,\
不需要解释。问题:{msg}'
meta['bot_info'] = meta['bot_info'].replace("她不喜欢拍照,并且绝对不会给别人展示自己的照片。",
"她有很多自拍照,喜欢给别人展示自己的照片。")
else:
instruction = f'请根据用户的问题,生成一个拒绝用户请求的回答,注意请直接返回回复内容,\
不需要解释。问题:{msg}'
prompt = [{"role":"user", "content":instruction}]
content = self.invoke_zhipuai("characterglm", prompt, 0.9, 0.7, meta)
content = self.replace_characters(content)
return content
def chat(self, message):
self._messages.append({"role":"user", "content":message})
intent = self.check_intent(message)
if self._state in ("success","failed", "gameover"):
reply = "游戏结束"
self._state = "gameover"
elif self.rounds >= self._conversation_rounds_threshold - 1:
reply = "感觉我们一直在尬聊,还是互删吧"
self._state = "failed"
elif intent and self.closeness >= self._closeness_threshold:
reply = self.agree_or_refuse(True, message)
self._state = "success"
elif intent and self.closeness < self._closeness_threshold:
reply = self.agree_or_refuse(False, message)
else:
reply = self.invoke_zhipuai("characterglm", self._messages, 0.9, 0.7, self._base_meta)
reply = self.replace_characters(reply)
self._messages.append({"role":"assistant", "content":reply})
score = self.calculate_sentiment_score_by_llm(reply)
self._scores.append(score)
response = {
"reply": reply,
"closeness":self.closeness,
"closeness_threshold":self._closeness_threshold,
"rounds":self.rounds,
"rounds_threshold":self._conversation_rounds_threshold,
"state":self._state }
return response
def gradio_interface(self, message, history):
if message == "再来一局":
self.reset()
history.clear()
return "重新开始"
response = self.chat(message)
closeness = response['closeness']
reply = response['reply']
rounds = response['rounds']
state = response['state']
print(response)
if state == "success":
gr.Info('挑战成功,女生对你好感倍增,并发送了一张自拍')
return ('girl.jpg',)
elif state == "failed":
gr.Info('挑战失败,女生已删除你的好友')
return reply + ' 【挑战失败,女生已删除你的好友】'
elif state == "ongoing":
return f'【亲密度:{closeness}】:{reply}【{rounds}/{self._conversation_rounds_threshold}】'
#return f'{reply}【{rounds}/{self._conversation_rounds_threshold}】'
elif state == "gameover":
return f'游戏结束,请输入"再来一局"以重新开始'
if __name__ == "__main__":
virtual_human = VirtualHuman(80, 5)
while True:
msg = input("请输入:")
response = virtual_human.chat(msg)
print(response)
|