|
|
|
import os |
|
import uuid |
|
|
|
import gradio as gr |
|
import modelscope_studio.components.antd as antd |
|
import modelscope_studio.components.antdx as antdx |
|
import modelscope_studio.components.base as ms |
|
from openai import OpenAI |
|
from dotenv import load_dotenv, dotenv_values |
|
load_dotenv() |
|
|
|
|
|
client = OpenAI( |
|
base_url="https://api-inference.huggingface.co/v1", |
|
api_key=os.environ.get('API_KEY') |
|
) |
|
|
|
|
|
model_links = { |
|
"GPT-4o": "meta-llama/Meta-Llama-3-8B-Instruct", |
|
"GPT-4": "meta-llama/Meta-Llama-3.1-70B-Instruct", |
|
} |
|
|
|
def reset_conversation(): |
|
''' |
|
Resets Conversation |
|
''' |
|
st.session_state.conversation = [] |
|
st.session_state.messages = [] |
|
return None |
|
|
|
|
|
|
|
|
|
|
|
models =[key for key in model_links.keys()] |
|
|
|
|
|
selected_model = st.sidebar.selectbox("Select a GPT model", models) |
|
|
|
|
|
st.sidebar.button('New Chat', on_click=reset_conversation) |
|
|
|
|
|
temp_values = st.sidebar.slider('ChatGPT Temperature', 0.0, 1.0, (0.5)) |
|
st.sidebar.markdown("Temperature in ChatGPT affects the quality and coherence of the generated text.") |
|
st.sidebar.markdown("**For optimum results, we recommend selecting a temperature between 0.5 and 0.7**") |
|
|
|
|
|
|
|
st.sidebar.markdown("*The content created may not be accurate.*") |
|
st.sidebar.markdown("\n Our website: [Chat-GPT-Free.com](https://chat-gpt-free.com/).") |
|
|
|
|
|
if "prev_option" not in st.session_state: |
|
st.session_state.prev_option = selected_model |
|
|
|
if st.session_state.prev_option != selected_model: |
|
st.session_state.messages = [] |
|
|
|
st.session_state.prev_option = selected_model |
|
reset_conversation() |
|
|
|
|
|
|
|
|
|
repo_id = model_links[selected_model] |
|
|
|
|
|
st.subheader(f'[Chat-GPT-Free.com](https://chat-gpt-free.com/) with AI model {selected_model}') |
|
|
|
|
|
|
|
if selected_model not in st.session_state: |
|
st.session_state[selected_model] = model_links[selected_model] |
|
|
|
|
|
if "messages" not in st.session_state: |
|
st.session_state.messages = [] |
|
|
|
|
|
|
|
for message in st.session_state.messages: |
|
with st.chat_message(message["role"]): |
|
st.markdown(message["content"]) |
|
|
|
|
|
|
|
|
|
if prompt := st.chat_input(f"Hi. I'm {selected_model}. How can I help you today?"): |
|
|
|
with st.chat_message("user"): |
|
st.markdown(prompt) |
|
|
|
st.session_state.messages.append({"role": "user", "content": prompt}) |
|
|
|
|
|
|
|
with st.chat_message("assistant"): |
|
try: |
|
stream = client.chat.completions.create( |
|
model=model_links[selected_model], |
|
messages=[ |
|
{"role": m["role"], "content": m["content"]} |
|
for m in st.session_state.messages |
|
], |
|
temperature=temp_values, |
|
stream=True, |
|
max_tokens=3000, |
|
) |
|
|
|
response = st.write_stream(stream) |
|
|
|
except Exception as e: |
|
|
|
response = "The GPT is overloaded!\ |
|
\n Repeat your request later :( " |
|
st.write(response) |
|
|
|
|
|
|
|
st.session_state.messages.append({"role": "assistant", "content": response}) |
|
css = """ |
|
.gradio-container { |
|
padding: 0 !important; |
|
} |
|
.gradio-container > main.fillable { |
|
padding: 0 !important; |
|
} |
|
#chatbot { |
|
height: calc(100vh - 21px - 16px); |
|
} |
|
#chatbot .chatbot-conversations { |
|
height: 100%; |
|
background-color: var(--ms-gr-ant-color-bg-layout); |
|
} |
|
#chatbot .chatbot-conversations .chatbot-conversations-list { |
|
padding-left: 0; |
|
padding-right: 0; |
|
} |
|
#chatbot .chatbot-chat { |
|
padding: 32px; |
|
height: 100%; |
|
} |
|
@media (max-width: 768px) { |
|
#chatbot .chatbot-chat { |
|
padding: 0; |
|
} |
|
} |
|
#chatbot .chatbot-chat .chatbot-chat-messages { |
|
flex: 1; |
|
} |
|
#chatbot .chatbot-chat .chatbot-chat-messages .chatbot-chat-message .chatbot-chat-message-footer { |
|
visibility: hidden; |
|
opacity: 0; |
|
transition: opacity 0.2s; |
|
} |
|
#chatbot .chatbot-chat .chatbot-chat-messages .chatbot-chat-message:last-child .chatbot-chat-message-footer { |
|
visibility: visible; |
|
opacity: 1; |
|
} |
|
#chatbot .chatbot-chat .chatbot-chat-messages .chatbot-chat-message:hover .chatbot-chat-message-footer { |
|
visibility: visible; |
|
opacity: 1; |
|
} |
|
""" |
|
|
|
|
|
def logo(): |
|
with antd.Typography.Title(level=1, |
|
elem_style=dict(fontSize=24, |
|
padding=8, |
|
margin=0)): |
|
with antd.Flex(align="center", gap="small", justify="center"): |
|
antd.Image(qwen_logo, |
|
preview=False, |
|
alt="logo", |
|
width=24, |
|
height=24) |
|
ms.Span("QwQ-32B") |
|
|
|
|
|
with gr.Blocks(css=css, fill_width=True) as demo: |
|
state = gr.State({ |
|
"conversations_history": {}, |
|
"conversations": [], |
|
"conversation_id": "", |
|
"editing_message_index": -1, |
|
}) |
|
|
|
with ms.Application(), antdx.XProvider( |
|
theme=DEFAULT_THEME, locale=DEFAULT_LOCALE), ms.AutoLoading(): |
|
with antd.Row(gutter=[20, 20], wrap=False, elem_id="chatbot"): |
|
|
|
with antd.Col(md=dict(flex="0 0 260px", span=24, order=0), |
|
span=0, |
|
order=1, |
|
elem_classes="chatbot-conversations"): |
|
with antd.Flex(vertical=True, |
|
gap="small", |
|
elem_style=dict(height="100%")): |
|
|
|
logo() |
|
|
|
|
|
with antd.Button(value=None, |
|
color="primary", |
|
variant="filled", |
|
block=True) as add_conversation_btn: |
|
ms.Text(get_text("New Conversation", "新建对话")) |
|
with ms.Slot("icon"): |
|
antd.Icon("PlusOutlined") |
|
|
|
|
|
with antdx.Conversations( |
|
elem_classes="chatbot-conversations-list", |
|
) as conversations: |
|
with ms.Slot('menu.items'): |
|
with antd.Menu.Item( |
|
label="Delete", key="delete", danger=True |
|
) as conversation_delete_menu_item: |
|
with ms.Slot("icon"): |
|
antd.Icon("DeleteOutlined") |
|
|
|
with antd.Col(flex=1, elem_style=dict(height="100%")): |
|
with antd.Flex(vertical=True, |
|
gap="middle", |
|
elem_classes="chatbot-chat"): |
|
|
|
with antdx.Bubble.List( |
|
items=DEFAULT_CONVERSATIONS_HISTORY, |
|
elem_classes="chatbot-chat-messages") as chatbot: |
|
|
|
with ms.Slot("roles"): |
|
|
|
with antdx.Bubble.List.Role( |
|
role="placeholder", |
|
styles=dict(content=dict(width="100%")), |
|
variant="borderless"): |
|
with ms.Slot("messageRender"): |
|
with antd.Space( |
|
direction="vertical", |
|
size=16, |
|
elem_style=dict(width="100%")): |
|
with antdx.Welcome( |
|
styles=dict(icon=dict( |
|
flexShrink=0)), |
|
variant="borderless", |
|
title=get_text( |
|
"Hello, I'm QwQ-32B", |
|
"你好,我是 QwQ-32B"), |
|
description=get_text( |
|
"You can type text to get started.", |
|
"你可以输入文本开始对话。"), |
|
): |
|
with ms.Slot("icon"): |
|
antd.Image(qwen_logo, |
|
preview=False) |
|
with antdx.Prompts(title=get_text( |
|
"How can I help you today?", |
|
"有什么我能帮助你的吗?"), |
|
styles={ |
|
"list": { |
|
"width": |
|
'100%', |
|
}, |
|
"item": { |
|
"flex": 1, |
|
}, |
|
}) as prompts: |
|
for item in DEFAULT_PROMPTS: |
|
with antdx.Prompts.Item( |
|
label=item["category"] |
|
): |
|
for prompt in item[ |
|
"prompts"]: |
|
antdx.Prompts.Item( |
|
description=prompt, |
|
) |
|
|
|
|
|
with antdx.Bubble.List.Role( |
|
role="user", |
|
placement="end", |
|
elem_classes="chatbot-chat-message", |
|
class_names=dict( |
|
footer="chatbot-chat-message-footer"), |
|
styles=dict(content=dict( |
|
maxWidth="100%", |
|
overflow='auto', |
|
))): |
|
with ms.Slot( |
|
"messageRender", |
|
params_mapping="(content) => content"): |
|
|
|
ms.Markdown() |
|
with ms.Slot("footer", |
|
params_mapping="""(bubble) => { |
|
return { |
|
copy_btn: { |
|
copyable: { text: typeof bubble.content === 'string' ? bubble.content : bubble.content?.text, tooltips: false }, |
|
}, |
|
edit_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled }, |
|
delete_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled }, |
|
}; |
|
}"""): |
|
with antd.Typography.Text( |
|
copyable=dict(tooltips=False), |
|
as_item="copy_btn"): |
|
with ms.Slot("copyable.icon"): |
|
with antd.Button(value=None, |
|
size="small", |
|
color="default", |
|
variant="text"): |
|
with ms.Slot("icon"): |
|
antd.Icon("CopyOutlined") |
|
with antd.Button(value=None, |
|
size="small", |
|
color="default", |
|
variant="text"): |
|
with ms.Slot("icon"): |
|
antd.Icon("CheckOutlined") |
|
with antd.Button(value=None, |
|
size="small", |
|
color="default", |
|
variant="text", |
|
as_item="edit_btn" |
|
) as user_edit_btn: |
|
with ms.Slot("icon"): |
|
antd.Icon("EditOutlined") |
|
with antd.Popconfirm( |
|
title="Delete the message", |
|
description= |
|
"Are you sure to delete this message?", |
|
ok_button_props=dict(danger=True), |
|
as_item="delete_btn" |
|
) as user_delete_popconfirm: |
|
with antd.Button(value=None, |
|
size="small", |
|
color="default", |
|
variant="text", |
|
as_item="delete_btn"): |
|
with ms.Slot("icon"): |
|
antd.Icon("DeleteOutlined") |
|
|
|
|
|
with antdx.Bubble.List.Role( |
|
role="assistant", |
|
placement="start", |
|
elem_classes="chatbot-chat-message", |
|
class_names=dict( |
|
footer="chatbot-chat-message-footer"), |
|
styles=dict(content=dict( |
|
maxWidth="100%", overflow='auto'))): |
|
with ms.Slot("avatar"): |
|
antd.Avatar( |
|
os.path.join(os.path.dirname(__file__), |
|
"qwen.png")) |
|
with ms.Slot( |
|
"messageRender", |
|
params_mapping="""(content, bubble) => { |
|
const reason_content = bubble?.meta?.reason_content |
|
const has_error = bubble?.meta?.error |
|
return { |
|
reasoning: reason_content || content, |
|
reasoning_container: has_error ? { style: { display: 'none' } } : undefined, |
|
answer: { |
|
value: reason_content || has_error ? content : undefined |
|
}, |
|
collapse_label: bubble.meta?.thought_end_message, |
|
collapse_progress: bubble.meta?.thought_end_message ? { style: { display: 'none' } } : undefined, |
|
canceled: bubble.meta?.canceled ? undefined : { style: { display: 'none' } } |
|
} |
|
}"""): |
|
with antd.Flex(vertical=True, |
|
gap="middle"): |
|
with antd.Collapse( |
|
default_active_key=[ |
|
"reasoning" |
|
], |
|
as_item="reasoning_container"): |
|
with antd.Collapse.Item( |
|
key="reasoning"): |
|
with ms.Slot("label"): |
|
with antd.Space( |
|
size="middle"): |
|
ms.Span( |
|
get_text( |
|
"Thinking...", |
|
"思考中..."), |
|
as_item= |
|
"collapse_label") |
|
antd.Progress( |
|
percent="100", |
|
status="active", |
|
elem_style=dict( |
|
display="flex", |
|
alignItems= |
|
"center", |
|
), |
|
show_info=False, |
|
size=[110, 5], |
|
as_item= |
|
"collapse_progress" |
|
) |
|
with antd.Alert( |
|
type="warning"): |
|
with ms.Slot( |
|
"description"): |
|
ms.Markdown( |
|
as_item="reasoning" |
|
) |
|
ms.Markdown( |
|
as_item="answer", |
|
elem_classes="answer-content") |
|
|
|
antd.Divider(as_item="canceled") |
|
antd.Typography.Text(get_text( |
|
"Chat completion paused.", "聊天已暂停。"), |
|
as_item="canceled", |
|
type="warning") |
|
|
|
with ms.Slot("footer", |
|
params_mapping="""(bubble) => { |
|
if (bubble?.meta?.end) { |
|
return { |
|
copy_btn: { |
|
copyable: { text: bubble.content, tooltips: false }, |
|
}, |
|
regenerate_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled }, |
|
delete_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled }, |
|
edit_btn: { conversationKey: bubble.key, disabled: bubble.meta.disabled }, |
|
}; |
|
} |
|
return { actions_container: { style: { display: 'none' } } }; |
|
}"""): |
|
with ms.Div(as_item="actions_container"): |
|
with antd.Typography.Text( |
|
copyable=dict(tooltips=False), |
|
as_item="copy_btn"): |
|
with ms.Slot("copyable.icon"): |
|
with antd.Button( |
|
value=None, |
|
size="small", |
|
color="default", |
|
variant="text"): |
|
with ms.Slot("icon"): |
|
antd.Icon( |
|
"CopyOutlined") |
|
with antd.Button( |
|
value=None, |
|
size="small", |
|
color="default", |
|
variant="text"): |
|
with ms.Slot("icon"): |
|
antd.Icon( |
|
"CheckOutlined") |
|
|
|
with antd.Popconfirm( |
|
title=get_text( |
|
"Regenerate the message", |
|
"重新生成消息"), |
|
description=get_text( |
|
"Regenerate the message will also delete all subsequent messages.", |
|
"重新生成消息将会删除所有的后续消息。"), |
|
ok_button_props=dict( |
|
danger=True), |
|
as_item="regenerate_btn" |
|
) as chatbot_regenerate_popconfirm: |
|
with antd.Button( |
|
value=None, |
|
size="small", |
|
color="default", |
|
variant="text", |
|
as_item="regenerate_btn", |
|
): |
|
with ms.Slot("icon"): |
|
antd.Icon("SyncOutlined") |
|
with antd.Button(value=None, |
|
size="small", |
|
color="default", |
|
variant="text", |
|
as_item="edit_btn" |
|
) as chatbot_edit_btn: |
|
with ms.Slot("icon"): |
|
antd.Icon("EditOutlined") |
|
with antd.Popconfirm( |
|
title=get_text("Delete the message", "删除消息"), |
|
description=get_text( |
|
"Are you sure to delete this message?", |
|
"确定要删除这条消息吗?"), |
|
ok_button_props=dict( |
|
danger=True), |
|
as_item="delete_btn" |
|
) as chatbot_delete_popconfirm: |
|
with antd.Button( |
|
value=None, |
|
size="small", |
|
color="default", |
|
variant="text", |
|
as_item="delete_btn"): |
|
with ms.Slot("icon"): |
|
antd.Icon("DeleteOutlined") |
|
|
|
|
|
with antdx.Suggestion( |
|
items=DEFAULT_SUGGESTIONS, |
|
|
|
should_trigger="""(e, { onTrigger, onKeyDown }) => { |
|
switch(e.key) { |
|
case '/': |
|
onTrigger() |
|
break |
|
case 'ArrowRight': |
|
case 'ArrowLeft': |
|
case 'ArrowUp': |
|
case 'ArrowDown': |
|
break; |
|
default: |
|
onTrigger(false) |
|
} |
|
onKeyDown(e) |
|
}""") as suggestion: |
|
with ms.Slot("children"): |
|
with antdx.Sender(placeholder=get_text( |
|
"Enter / to get suggestions", |
|
"输入 / 获取建议"), ) as sender: |
|
with ms.Slot("prefix"): |
|
|
|
with antd.Tooltip(title=get_text( |
|
"Clear Conversation History", |
|
"清空对话历史"), ): |
|
with antd.Button( |
|
value=None, |
|
type="text") as clear_btn: |
|
with ms.Slot("icon"): |
|
antd.Icon("ClearOutlined") |
|
|
|
|
|
with antd.Modal(title=get_text("Edit Message", "编辑消息"), |
|
open=False, |
|
centered=True, |
|
width="60%") as edit_modal: |
|
edit_textarea = antd.Input.Textarea(auto_size=dict(minRows=2, |
|
maxRows=6), |
|
elem_style=dict(width="100%")) |
|
|
|
if save_history: |
|
browser_state = gr.BrowserState( |
|
{ |
|
"conversations_history": {}, |
|
"conversations": [], |
|
}, |
|
storage_key="qwen_qwq_chatbot_storage") |
|
state.change(fn=Gradio_Events.update_browser_state, |
|
inputs=[state], |
|
outputs=[browser_state]) |
|
|
|
demo.load(fn=Gradio_Events.apply_browser_state, |
|
inputs=[browser_state, state], |
|
outputs=[conversations, state]) |
|
|
|
add_conversation_btn.click(fn=Gradio_Events.new_chat, |
|
inputs=[state], |
|
outputs=[conversations, chatbot, state]) |
|
conversations.active_change(fn=Gradio_Events.select_conversation, |
|
inputs=[state], |
|
outputs=[conversations, chatbot, state]) |
|
conversations.menu_click(fn=Gradio_Events.click_conversation_menu, |
|
inputs=[state], |
|
outputs=[conversations, chatbot, state]) |
|
prompts.item_click(fn=Gradio_Events.apply_prompt, outputs=[sender]) |
|
|
|
clear_btn.click(fn=Gradio_Events.clear_conversation_history, |
|
inputs=[state], |
|
outputs=[chatbot, state]) |
|
|
|
suggestion.select(fn=Gradio_Events.select_suggestion, |
|
inputs=[sender], |
|
outputs=[sender]) |
|
|
|
gr.on(triggers=[user_edit_btn.click, chatbot_edit_btn.click], |
|
fn=Gradio_Events.edit_message, |
|
inputs=[state], |
|
outputs=[edit_textarea, state]).then(fn=Gradio_Events.open_modal, |
|
outputs=[edit_modal]) |
|
edit_modal.ok(fn=Gradio_Events.confirm_edit_message, |
|
inputs=[edit_textarea, state], |
|
outputs=[chatbot, state]).then(fn=Gradio_Events.close_modal, |
|
outputs=[edit_modal]) |
|
edit_modal.cancel(fn=Gradio_Events.close_modal, outputs=[edit_modal]) |
|
gr.on(triggers=[ |
|
chatbot_delete_popconfirm.confirm, user_delete_popconfirm.confirm |
|
], |
|
fn=Gradio_Events.delete_message, |
|
inputs=[state], |
|
outputs=[chatbot, state]) |
|
|
|
regenerating_event = chatbot_regenerate_popconfirm.confirm( |
|
fn=Gradio_Events.regenerate_message, |
|
inputs=[state], |
|
outputs=[sender, clear_btn, conversation_delete_menu_item, add_conversation_btn, conversations, chatbot, state]) |
|
|
|
submit_event = sender.submit(fn=Gradio_Events.submit, |
|
inputs=[sender, state], |
|
outputs=[sender, clear_btn, conversation_delete_menu_item, |
|
add_conversation_btn, conversations,chatbot, state]) |
|
sender.cancel(fn=None, cancels=[submit_event, regenerating_event]) |
|
sender.cancel(fn=Gradio_Events.cancel, |
|
inputs=[state], |
|
outputs=[ |
|
sender, conversation_delete_menu_item, clear_btn, |
|
conversations, add_conversation_btn, chatbot, state |
|
]) |
|
|
|
if __name__ == "__main__": |
|
demo.queue(default_concurrency_limit=200).launch(ssr_mode=False, max_threads=200) |
|
|