File size: 8,264 Bytes
934ceb1
 
 
 
 
 
 
 
 
 
 
e6dddd8
a6f0e8b
 
 
 
 
 
934ceb1
 
 
 
 
 
 
9b6cf76
934ceb1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e6dddd8
a6f0e8b
 
934ceb1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a6f0e8b
934ceb1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dc99f42
934ceb1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dc99f42
934ceb1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60332a3
934ceb1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import PIL.Image
import numpy as np
import os,re,pytz,time
import streamlit as st
from datetime import datetime
import google.generativeai as genai
import streamlit.components.v1 as components
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image

UTC_8 = pytz.timezone('Asia/Shanghai')
#cache func
@st.cache_resource
def load_my_model():
    model = load_model("model/zha2024_6.h5")
    return model
    
my_model = load_my_model()
target_size = (300, 300)
class_labels = {0: '炭黑组', 1: '正常发挥', 2: '炫彩组', 3: '糊糊组', 4: '炸组日常', 5: '凡尔赛',6: '非食物'}
predicted_class=''
#Set up the Gemini model and API key
#https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/gemini?hl=zh-cn
MY_KEY= os.environ.get("GOOGLE_API_KEY")
genai.configure(api_key=MY_KEY)
gemini_model = genai.GenerativeModel('gemini-pro-vision')
neutral=os.environ.get("sys_info_0")
toxic=os.environ.get("sys_info_1")
heartfelt=os.environ.get("sys_info_2")
chilly_list=os.environ.get("X").split(",")
default_prompt=''

generation_config = {
  "temperature": 0.99,
  "top_p": 1,
  "top_k": 40,
  "max_output_tokens": 2048,
    "candidate_count":1
}
safety_settings = [
  {
    "category": "HARM_CATEGORY_HARASSMENT",
    "threshold": "BLOCK_NONE"
  },
  {
    "category": "HARM_CATEGORY_HATE_SPEECH",
    "threshold": "BLOCK_NONE"
  },
  {
    "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
    "threshold": "BLOCK_NONE"
  },
  {
    "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
    "threshold": "BLOCK_NONE"
  }
]

#functions
@st.cache_data
def preprocess_image_cached(img_path, target_size):
    img = image.load_img(img_path, target_size=target_size)
    img_array = image.img_to_array(img)
    img_array = np.expand_dims(img_array, axis=0)
    return img_array

def chilly_words_killer(text,words_list):
    for word in words_list:
        pattern = re.compile(re.escape(word), re.IGNORECASE)
        text = pattern.sub("**😮", text)
    return text    

def get_critic_info(review_style):
    if review_style == '默认':
        default_prompt = neutral
        critic_name = 'SavorBalancer'
        avatar = '👩‍🍳'
    elif review_style == '毒舌👾':
        default_prompt = toxic
        critic_name = 'SpicyCritique'
        avatar = '😈'
    elif review_style == '暖心🍀':
        default_prompt = heartfelt
        critic_name = 'GentleGourmet'
        avatar = '🤗'
    else:
        raise ValueError(f'Invalid review style: {review_style}')
    return default_prompt, critic_name, avatar

def img_score(img_raw_path):
    global predicted_class
    img_array = preprocess_image_cached(img_raw_path, target_size)
    predictions = my_model.predict(img_array)
    predicted_class_index = np.argmax(predictions, axis=-1)
    predicted_class = class_labels[predicted_class_index[0]]
    class_probabilities = {label: prob for label, prob in zip(class_labels.values(), predictions[0])}
    
    score={k: round(v * 100, 2) for k, v in class_probabilities.items()}
    high_score_float=predictions[0,(predicted_class_index[0])]
    high_score=round(high_score_float*100,2)
    return score,high_score

def score_desc(score):
    if score > 90:
        return "这妥妥的属于"
    elif score >= 70 and score <= 90:
        return "这大概率属于"
    elif score >= 40 and score <= 70:
        return "这可能属于"
    else:
        return "我猜这属于"


def review_waiting(_class, critic_name):
    if _class == '非食物':
        return  '图里面好像没有食物吧❓点评可能会说些无关的'
    elif critic_name == 'SavorBalancer':
        return '🍴品尝中,正在构思点评'
    elif critic_name == 'SpicyCritique':
         return '不要催啦,我这不正在吃吗💢'
    elif critic_name == 'GentleGourmet':
        return '正在为你种彩虹🌈'
    

def gemini_bot(default_prompt,img_raw_path,_class):
    img = PIL.Image.open(img_raw_path)
    model = gemini_model
    klass="当前食物类型是:"+_class
    prompt=klass+default_prompt
    response = model.generate_content([prompt, img],
    stream=False,
    safety_settings=safety_settings,
    generation_config=generation_config)
    response.resolve()
    response_text=f'''{response.text}'''
    final_response=chilly_words_killer(response_text,chilly_list)
    return final_response

def review():
    if predicted_class is not None:
        with st.spinner(review_waiting(predicted_class, critic_name)):
            print(f"{datetime.now(UTC_8).strftime('%m-%d %H:%M:%S')}--Start Reviewing")
            final_response = gemini_bot(default_prompt, img_raw_path, predicted_class)
            with st.chat_message(critic_name, avatar=avatar):
                st.write(final_response)
                st.button("再次点评", key="1")
            print(f"{datetime.now(UTC_8).strftime('%m-%d %H:%M:%S')}--Complete\n💣💣💣")
            info('#edfde2','#78817a','🆗点评完毕,内容由AI生成,仅供娱乐',55)
          
def info(bg_color,font_color,text,height):
    html=f'''<html><style>
body {{
   margin: 0;
   padding: 0;
   color: #3b4740;
   background-color: transparent;
}}
.container {{
   max-width: 100%;
   margin: 0 auto;
   padding: 20px;
   font-size: 15px;
   color:{font_color}
    display: flex;
   justify-content: space-between;
   align-items: center;
   background-color: #f8e9a000;
   padding: 15px;
   border-radius: 10px;
   line-height: 1.6; 
   border: #fde2e4 0px solid;
   background-color:{bg_color} ;
}}
</style><body><div class="container">
    {text}
</body></html>'''    
    components.html(html,height=height)
            
#Streamlit UI
#Guide: https://docs.streamlit.io/library/api-reference
#st.header("🧨ZhazuEvaluator")
#st.subheader('', divider='rainbow')
st.image('https://cdnjson.com/images/2024/01/30/banner7f1835c564c9b79c.png')
    
# Upload an image
bg_color='#e1f1fa'
border_font_color='#78817a'
css=f'''<style>
[data-testid="stFileUploadDropzone"]{{background-color:{bg_color};color:{border_font_color}}}
[data-testid="baseButton-secondary"]{{background-color:{bg_color};border:1px {border_font_color} solid;color:{border_font_color}}}
[data-testid="baseButton-secondary"]>div[data-testid="stMarkdownContainer"] {{border: none;}}
div[data-testid="stFileDropzoneInstructions"]>div>span::after {{
       content:"✨来上传一张你的得意之作,PC可直接拖放上传";
       visibility:visible;
       display:block;
    }}

</style>'''
st.markdown(css,unsafe_allow_html=True)

img_raw_path = st.file_uploader("上传图片", type=['png', 'jpg', 'jpeg', 'webp'], label_visibility="collapsed")

col1, col2 = st.columns(2)
my_image = ""
if not img_raw_path is None:
    my_image = img_raw_path.read()
    my_image = PIL.Image.open(img_raw_path)
    print(f"{datetime.now(UTC_8).strftime('%m-%d %H:%M:%S')}--IMG uploaded")
    with col1:
       st.image(my_image, caption='✅图片已上传', width=350)

# Predict the class of the image
if my_image:
    with st.spinner('💥正在打分中...'):
        print(f"{datetime.now(UTC_8).strftime('%m-%d %H:%M:%S')}--Start  Classification")
        score,high_score=img_score(img_raw_path)
        with col2:
            st.bar_chart(score, color='#fdd3de',width=412)
        score_noti=f"📝{score_desc(high_score)}{predicted_class}➡️得分:{high_score}"
        info('#edfde2','#78817a',score_noti,55)
        
review_style= st.radio(
"请选择点评文字风格",
["默认", "毒舌👾", "暖心🍀"],
    index=0, horizontal=True
)
default_prompt, critic_name, avatar=get_critic_info(review_style)

#review
if my_image:
    review()
    
announcements='''注意事项\n
1.上传的图片有一定概率不会被识别,可能出现点评完全和图片无关的情况,特别是非食物图片\n
2.如果AI开始说车轱辘话,不断重复某个句式,内容也相关性不大,请重新点评。\n
3.毒舌点评可能会出现轻微冒犯用语,请不要放在心上。
'''
st.warning(announcements)
left_blank, centre,last_blank = st.columns([3.4,2,3])
with centre:
    st.image("https://visitor-badge.laobi.icu/badge?page_id=Ailyth/z2024&left_text=MyDearVisitors&left_color=pink&right_color=Paleturquoise")