File size: 10,079 Bytes
a5b48a7
 
 
df24d9c
a5b48a7
0b9c45d
a5b48a7
c003b8d
a5b48a7
4097bac
 
e2a026e
5158e04
4097bac
9eb33c4
e2a026e
 
 
 
 
 
 
 
 
 
 
 
 
 
4097bac
5b3f957
7ca6d3a
 
 
1823a15
e9bb75c
 
 
 
 
 
 
4df72f2
7d3d77d
eb6f667
7d3d77d
b4b5ce5
7d3d77d
a272cb9
7d3d77d
e2a026e
5b3f957
5b6eec5
 
3c0c20b
 
0f925b8
 
 
 
 
 
3c0c20b
 
 
 
 
 
 
 
dfb47fb
 
 
 
 
5b6eec5
dfb47fb
7178e21
7ca6d3a
 
 
 
9504740
 
7178e21
 
 
7ca6d3a
 
7178e21
dfb47fb
 
6570427
583cdf6
dfb47fb
 
 
 
f4be3c5
dfb47fb
 
 
74bfe43
e265ae5
e9bb75c
 
7ca6d3a
 
3421166
7ca6d3a
3421166
8909c53
 
 
 
a5b48a7
 
e2a026e
 
0db6418
 
5c13efa
 
e2a026e
 
 
 
 
fa1169f
 
1b8f04a
e2a026e
 
fa1169f
 
1b8f04a
66afc6f
62664c3
41b12a8
ffef722
5b3f957
 
0b25d1f
5b3f957
7d3d77d
360577c
6eb3c68
 
 
 
a2df623
5b3f957
62664c3
6eb3c68
5b3f957
 
6eb3c68
 
 
 
25a4d3c
 
0b25d1f
5b3f957
 
cf47250
5b3f957
66afc6f
4db4ec7
dad0315
 
 
0d45e75
e2a026e
 
 
 
dad0315
4097bac
e5f7a31
 
5b3f957
0b25d1f
 
f1d1dd8
 
 
 
 
 
 
 
 
 
 
 
 
 
a44076e
62664c3
 
1b8f04a
 
f1d1dd8
3704691
 
 
1027c92
f1d1dd8
 
 
e5f7a31
f1d1dd8
 
 
 
 
ca86104
e2a026e
 
 
4097bac
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
import gradio as gr
import requests
import os
import pandas as pd
import json
import random
from elo import update_elo_ratings  # Custom function for ELO ratings
enable_btn = gr.Button.update(interactive=True)

import sqlite3

import pymongo
password=os.environ.get("MONGODB")
def init_database():
    client = pymongo.MongoClient(f"mongodb+srv://new-user:{password}@cluster0.xb2urf6.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0")
    db = client["elo_ratings"]
    collection = db["elo_ratings"]
    return collection

def get_user_elo_ratings(collection):
    rows = list(collection.find())
    if rows:
        return {row['bot_name']: {'elo_rating': row['elo_rating'], 'games_played': row['games_played']} for row in rows}
    else:
        return {"default": {'elo_rating': 1200, 'games_played': 0}}

def update_elo_rating(collection, updated_ratings, winner, loser):
    collection.update_one({"bot_name": winner}, {"$set": {"elo_rating": updated_ratings[winner]['elo_rating'], "games_played": updated_ratings[winner]['games_played']}}, upsert=True)
    collection.update_one({"bot_name": loser}, {"$set": {"elo_rating": updated_ratings[loser]['elo_rating'], "games_played": updated_ratings[loser]['games_played']}}, upsert=True)

# Load chatbot URLs and model names from a JSON file
# Load chatbot model adapter names from a text file
with open('chatbots.txt', 'r') as file:
    chatbots = file.read().splitlines()
def clear_chat(state):
    # Reset state including the chatbot order
    state = {} if state is not None else state
    # Shuffle and reinitialize chatbots in the state
    bot_names = list(chatbots.keys())
    random.shuffle(bot_names)
    state['last_bots'] = [bot_names[0], bot_names[1]]
    # Reset other components
    return state, None, None, gr.Button.update(interactive=False), gr.Button.update(interactive=False), gr.Textbox.update(interactive=True), gr.Button.update(interactive=True)

global_elo_ratings=None

from datasets import load_dataset,DatasetDict,Dataset
import requests
import os


# Function to get bot response
def format_alpaca_prompt(state):
    alpaca_prompt = "Below is an instruction that describes a task. Write a response that appropriately completes the request."
    alpaca_prompt2 = "Below is an instruction that describes a task. Write a response that appropriately completes the request."
    for message in state["history"][0]:
        j=""
        if message['role']=='user':
            j="### Instruction:\n"
        else:
            j="### Response:\n"
        alpaca_prompt += j+ message['content']+"\n\n"
    for message in state["history"][1]:
        j=""
        if message['role']=='user':
            j="### Instruction:\n"
        else:
            j="### Response:\n"
        alpaca_prompt2 += j+ message['content']+"\n\n"
    return [alpaca_prompt+"### Response:\n",alpaca_prompt2+"### Response:\n"]
import aiohttp
import asyncio
from tenacity import retry, stop_after_attempt, wait_exponential

async def get_bot_response(adapter_id, prompt, state, bot_index):
    alpaca_prompt = format_alpaca_prompt(state)
    print(alpaca_prompt)
    payload = {
        "inputs": alpaca_prompt[bot_index],
        "parameters": {
            "adapter_id": adapter_id,
            "adapter_source": "hub",
            "temperature": 1,
            "max_new_tokens": 100
        }
    }
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {os.environ.get('PREDIBASE_TOKEN')}"
    }
    async with aiohttp.ClientSession() as session:
        try:
            async with session.post("https://serving.app.predibase.com/79957f/deployments/v2/llms/mistral-7b-instruct/generate",
                                    json=payload, headers=headers, timeout=30) as response:
                if response.status == 200:
                    response_data = await response.json()
                    response_text = response_data.get('generated_text', '')
                else:
                    print(response.text)
                    response_text = "Sorry, I couldn't generate a response."
        except (aiohttp.ClientError, asyncio.TimeoutError):
            response_text = "Sorry, I couldn't generate a response."
    return response_text.split('### Instruction')[0]
async def chat_with_bots(user_input, state):
    # Use existing bot order from state if available, otherwise shuffle and initialize
    if 'last_bots' not in state or not state['last_bots']:
        random.shuffle(chatbots)
        state['last_bots'] = [chatbots[0], chatbots[1]]
    
    bot1_adapter, bot2_adapter = state['last_bots'][0], state['last_bots'][1]

    bot1_response, bot2_response = await asyncio.gather(
        get_bot_response(bot1_adapter, user_input, state, 0),
        get_bot_response(bot2_adapter, user_input, state, 1)
    )

    return bot1_response, bot2_response
def update_ratings(state, winner_index, collection):
    elo_ratings = get_user_elo_ratings(collection)
    winner = state['last_bots'][winner_index]
    loser = state['last_bots'][1 - winner_index]
    
    elo_ratings = update_elo_ratings(elo_ratings, winner, loser)
    update_elo_rating(collection, elo_ratings, winner, loser)
    return [('Winner: ', winner.replace('rwitz/','').replace('-lora','')), ('Loser: ', loser.replace('rwitz/','').replace('-lora',''))]
    
def vote_up_model(state, chatbot, chatbot2, collection):
    update_message = update_ratings(state, 0, collection)
    chatbot.append(update_message[0])
    chatbot2.append(update_message[1])
    return chatbot, chatbot2,gr.Button.update(interactive=False),gr.Button.update(interactive=False),gr.Textbox.update(interactive=False),gr.Button.update(interactive=False)  # Disable voting buttons
def vote_down_model(state, chatbot, chatbot2, collection):
    update_message = update_ratings(state, 1, collection)
    chatbot2.append(update_message[0])
    chatbot.append(update_message[1])
    return chatbot,chatbot2, gr.Button.update(interactive=False),gr.Button.update(interactive=False),gr.Textbox.update(interactive=False),gr.Button.update(interactive=False)  # Disable voting buttons

async def user_ask(state, chatbot1, chatbot2, textbox):
    global enable_btn
    user_input = textbox
    if len(user_input) > 200:
        user_input = user_input[:200]  # Limit user input to 200 characters

    # Updating state with the current ELO ratings
    state["elo_ratings"] = get_user_elo_ratings()
    if "history" not in state:
        state.update({'history': [[],[]]})
    state["history"][0].extend([
        {"role": "user", "content": user_input}])
    state["history"][1].extend([
        {"role": "user", "content": user_input}])
    # Chat with bots
    bot1_response, bot2_response = await chat_with_bots(user_input, state)
    state["history"][0].extend([
        {"role": "bot1", "content": bot1_response},
    ])
    state["history"][1].extend([
        {"role": "bot2", "content": bot2_response},
    ])
    
    chatbot1.append((user_input,bot1_response))
    chatbot2.append((user_input,bot2_response))

    # Keep only the last 10 messages in history
    state["history"] = state["history"][-10:]

    # Format the conversation in ChatML format

    return state, chatbot1, chatbot2, gr.update(value=''),enable_btn,enable_btn
import pandas as pd

# Function to generate leaderboard data

def generate_leaderboard(collection):
    rows = list(collection.find())
    leaderboard_data = pd.DataFrame(rows, columns=['bot_name', 'elo_rating', 'games_played'])
    leaderboard_data.columns = ['Chatbot', 'ELO Score', 'Games Played']
    return leaderboard_data
    
def refresh_leaderboard():
    return generate_leaderboard()
# Gradio interface setup
with gr.Blocks() as demo:
    state = gr.State({})
    with gr.Tab("Chatbot Arena"):
        with gr.Row():
            with gr.Column():
                chatbot1 = gr.Chatbot(label='Model A').style(height=600)
                upvote_btn_a = gr.Button(value="πŸ‘ Upvote A",interactive=False)
            
            with gr.Column():
                chatbot2 = gr.Chatbot(label='Model B').style(height=600)
                upvote_btn_b = gr.Button(value="πŸ‘ Upvote B",interactive=False)        
    
        textbox = gr.Textbox(placeholder="Enter your prompt (up to 200 characters)", max_chars=200)
        with gr.Row():
            submit_btn = gr.Button(value="Send")
            reset_btn = gr.Button(value="Reset")
        reset_btn.click(clear_chat, inputs=[state], outputs=[state, chatbot1, chatbot2, upvote_btn_a, upvote_btn_b,textbox,submit_btn])
        textbox.submit(user_ask, inputs=[state, chatbot1, chatbot2, textbox], outputs=[state, chatbot1, chatbot2, textbox,upvote_btn_a,upvote_btn_b], queue=True)
        submit_btn.click(user_ask, inputs=[state, chatbot1, chatbot2, textbox], outputs=[state, chatbot1, chatbot2, textbox,upvote_btn_a,upvote_btn_b], queue=True)
        upvote_btn_a.click(vote_up_model, inputs=[state, chatbot1,chatbot2], outputs=[chatbot1,chatbot2,upvote_btn_a,upvote_btn_b,textbox,submit_btn])
        upvote_btn_b.click(vote_down_model, inputs=[state, chatbot1,chatbot2], outputs=[chatbot1,chatbot2,upvote_btn_a,upvote_btn_b,textbox,submit_btn])
    with gr.Tab("Leaderboard"):
        try:
            leaderboard = gr.Dataframe(refresh_leaderboard())
        except:
            leaderboard=gr.Dataframe(columns=['Chatbot', 'ELO Score', 'Games Played'])
        refresh_btn = gr.Button("Refresh Leaderboard")

    # Function to refresh leaderboard


    # Event handler for the refresh button
    refresh_btn.click(refresh_leaderboard, inputs=[], outputs=[leaderboard])

    # Launch the Gradio interface
if __name__ == "__main__":
    collection = init_database()
    upvote_btn_a.click(vote_up_model, inputs=[state, chatbot1, chatbot2, collection], outputs=[chatbot1, chatbot2, upvote_btn_a, upvote_btn_b, textbox, submit_btn])
    upvote_btn_b.click(vote_down_model, inputs=[state, chatbot1, chatbot2, collection], outputs=[chatbot1, chatbot2, upvote_btn_a, upvote_btn_b, textbox, submit_btn])
    demo.launch(share=False)