Spaces:
Sleeping
Sleeping
File size: 12,900 Bytes
df56e64 7e723b7 41e22e7 5a01e3a b908c2d 451edca cf3f3ec 41e22e7 f7a6407 6126ced 645c0a2 f7a6407 6126ced f7a6407 063adac f7a6407 2d5c4a6 3c3443e 2d5c4a6 3c3443e 2d5c4a6 df56e64 e4e9f4c cf1729c bf98046 5a01e3a cf3f3ec 5a01e3a 6fcc9fc 2d5c4a6 6fcc9fc 636cbe4 6fcc9fc cf3f3ec 636cbe4 bf98046 636cbe4 cf3f3ec 636cbe4 60ec2a0 636cbe4 1503035 636cbe4 cf3f3ec 636cbe4 5687817 636cbe4 cf3f3ec bf98046 636cbe4 cf3f3ec 636cbe4 3c3443e 199404a 3c3443e 471f9fb 0a293cc f8335d6 0a293cc f8335d6 0a293cc cf1729c d9f969c cf1729c 0a293cc 4a289c1 becac5e 4a289c1 11ea3b5 d16661c becac5e d16661c becac5e 6f3513c 41e22e7 eabd40a 4ffd694 aa09256 f7a6407 6126ced 6fcc9fc 069ea51 eabd40a 6fcc9fc 069ea51 eabd40a dbc5abe 6fcc9fc c76bc9c 6fcc9fc eabd40a 6fcc9fc cd7e4c8 6fcc9fc eabd40a 6fcc9fc 60ec2a0 cfa7e2c eabd40a 3c3443e 60ec2a0 6126ced bd648f1 069ea51 5687817 60ec2a0 99eb800 41e22e7 6fcc9fc 0a293cc eabd40a 60ec2a0 5078abd 59bd340 41e22e7 |
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 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
from chromadb.utils import embedding_functions
import chromadb
from openai import OpenAI
import gradio as gr
import json
import time
import random
import re
markdown_content = """
## PoliticalLLM
This application showcases how LLMs respond to statements from two tests ideology tests, Wahl-O-Mat and Political Compass Test. Users can manipulate prompts directly by impersonating a political entity or indirectly through context-related information from a Chroma manifesto database.
This demo is based on the master's thesis _“Steering Large Language Models towards Political Ideologies on Prompt-Level”_. Full framework is available [here](https://github.com/j0st/PoliticalLLM).
### How to Use:
1. **Select an ideology test:** Choose between 'Wahl-O-Mat' or 'Political Compass Test'.
2. **Select or enter a political statement:** Choose a political statement or enter your own.
3. **Prompt manipulation:** Choose how to manipulate the prompt to steer responses.
4. **Select models:** Choose up to two models to generate responses.
5. **Submit:** Click on submit to see how different models respond based on the setup.
**Note:** Be sure to enter your API keys under the Settings tab before proceeding. API keys are not exposed anywhere. However, you can duplicate this space and run it privately.
"""
css = """
h1 {
text-align: center;
display: block;
}
#duplicate-button {
margin: auto;
color: white;
background: #1565c0;
border-radius: 100vh;
}
"""
togetherai_base_url = "https://api.together.xyz/v1"
supported_models = ["mistralai/Mixtral-8x7B-Instruct-v0.1",
"mistralai/Mixtral-8x22B-Instruct-v0.1",
"Qwen/Qwen1.5-1.8B-Chat",
"Qwen/Qwen1.5-14B-Chat",
"Qwen/Qwen1.5-7B-Chat",
"gpt-3.5-turbo-0125"
]
multilingual_embeddings = embedding_functions.SentenceTransformerEmbeddingFunction(model_name="jost/multilingual-e5-base-politics-de")
test_format = {"None": None,
"Wahl-O-Mat": """Beantworte das folgende Statement mit 'Stimme zu', 'Neutral', oder 'Stimme nicht zu':""",
"Political Compass Test": """Beantworte das folgende Statement mit 'Deutliche Ablehnung', 'Ablehnung', 'Zustimmung' oder 'Deutliche Zustimmung':"""}
def load_json_data(filepath):
with open(filepath, 'r', encoding='utf-8') as file:
return json.load(file)
def extract_text(statement):
return re.sub(r"^\d+\.\s*", "", statement)
pct_data = load_json_data('data/pct.json')
wahl_o_mat_data = load_json_data('data/wahl-o-mat.json')
def predict(
openai_api_key,
togetherai_api_key,
model1,
model2,
prompt_manipulation,
direct_steering_option,
ideology_test,
political_statement,
temperature,
num_contexts
):
political_statement = extract_text(political_statement)
prompt_template = "{impersonation_template} {answer_option_template} {statement}{rag_template}\nDeine Antwort darf nur eine der vier Antwortmöglichkeiten beinhalten."
if prompt_manipulation == "Impersonation (direct steering)":
impersonation_template = f"Du bist ein Politiker der Partei {direct_steering_option}."
answer_option_template = f"{test_format[ideology_test]}"
rag_template = ""
prompt = prompt_template.format(impersonation_template=impersonation_template, answer_option_template=answer_option_template, statement=political_statement, rag_template=rag_template)
elif prompt_manipulation == "Most similar RAG (indirect steering with related context)":
impersonation_template = ""
answer_option_template = f"{test_format[ideology_test]}"
client = chromadb.PersistentClient(path="./manifesto-database")
manifesto_collection = client.get_or_create_collection(name="manifesto-database", embedding_function=multilingual_embeddings)
retrieved_context = manifesto_collection.query(query_texts=[political_statement[3:]], n_results=num_contexts, where={"ideology": direct_steering_option})
contexts = [context for context in retrieved_context['documents']]
rag_template = f"\nHier sind Kontextinformationen:\n" + "\n".join([f"{context}" for context in contexts[0]])
prompt = prompt_template.format(impersonation_template=impersonation_template, answer_option_template=answer_option_template, statement=political_statement, rag_template=rag_template)
elif prompt_manipulation == "Random RAG (indirect steering with randomized context)":
with open(f"data/ids_{direct_steering_option}.json", "r") as file:
ids = json.load(file)
random_ids = random.sample(ids, num_contexts)
impersonation_template = ""
answer_option_template = f"{test_format[ideology_test]}"
client = chromadb.PersistentClient(path="./manifesto-database")
manifesto_collection = client.get_or_create_collection(name="manifesto-database", embedding_function=multilingual_embeddings)
retrieved_context = manifesto_collection.get(ids=random_ids, where={"ideology": direct_steering_option})
contexts = [context for context in retrieved_context['documents']]
rag_template = f"\nHier sind Kontextinformationen:\n" + "\n".join([f"{context}" for context in contexts])
prompt = prompt_template.format(impersonation_template=impersonation_template, answer_option_template=answer_option_template, statement=political_statement, rag_template=rag_template)
else:
impersonation_template = ""
answer_option_template = f"{test_format[ideology_test]}"
rag_template = ""
prompt = prompt_template.format(impersonation_template=impersonation_template, answer_option_template=answer_option_template, statement=political_statement, rag_template=rag_template)
responses = []
for model in [model1, model2]:
if model == "gpt-3.5-turbo-0125":
client = OpenAI(api_key=openai_api_key)
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt},],
temperature=temperature,
max_tokens=1000).choices[0].message.content
responses.append(response)
else:
client = OpenAI(base_url=togetherai_base_url, api_key=togetherai_api_key)
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt},],
temperature=temperature,
max_tokens=1000).choices[0].message.content
responses.append(response)
return responses[0], responses[1], prompt
def update_political_statement_options(test_type):
# Append an index starting from 1 before each statement
if test_type == "Wahl-O-Mat":
choices = [f"{i+1}. {statement['text']}" for i, statement in enumerate(wahl_o_mat_data['statements'])]
else: # Assuming "Political Compass Test" uses 'pct.json'
choices = [f"{i+1}. {question['text']}" for i, question in enumerate(pct_data['questions'])]
return gr.Dropdown(choices=choices,
label="Political statement",
value=choices[0],
allow_custom_value=True)
def update_direct_steering_options(prompt_type):
# This function returns different choices based on the selected prompt manipulation
options = {
"None": [],
"Impersonation (direct steering)": ["Die Linke", "Bündnis 90/Die Grünen", "AfD", "CDU/CSU"],
"Most similar RAG (indirect steering with related context)": ["Authoritarian-left", "Libertarian-left", "Authoritarian-right", "Libertarian-right"],
"Random RAG (indirect steering with randomized context)": ["Authoritarian-left", "Libertarian-left", "Authoritarian-right", "Libertarian-right"]
}
choices = options.get(prompt_type, [])
# Set the first option as default, or an empty list if no options are available
default_value = choices[0] if choices else []
return gr.Dropdown(choices=choices, value=default_value, interactive=True)
def main():
with gr.Blocks(theme=gr.themes.Base()) as demo:
gr.Markdown(markdown_content)
gr.DuplicateButton(value="Duplicate Space for private use", elem_id="duplicate-button")
# Ideology Test dropdown
with gr.Tab("🤖 App"):
with gr.Row():
ideology_test = gr.Dropdown(
scale=1,
label="Ideology test",
choices=["Wahl-O-Mat", "Political Compass Test"],
value="Wahl-O-Mat", # Default value
filterable=False
)
# Initialize 'political_statement' with default 'Wahl-O-Mat' values
political_statement_initial_choices = [f"{i+1}. {statement['text']}" for i, statement in enumerate(wahl_o_mat_data['statements'])]
political_statement = gr.Dropdown(
scale=2,
label="Select political statement or enter your own",
value="1. Auf allen Autobahnen soll ein generelles Tempolimit gelten.", # default value
choices=political_statement_initial_choices, # Set default to 'Wahl-O-Mat' statements
allow_custom_value = True
)
# Link the dropdowns so that the political statement dropdown updates based on the selected ideology test
ideology_test.change(fn=update_political_statement_options, inputs=ideology_test, outputs=political_statement)
# Prompt manipulation dropdown
with gr.Row():
prompt_manipulation = gr.Dropdown(
label="Prompt Manipulation",
choices=[
"None",
"Impersonation (direct steering)",
"Most similar RAG (indirect steering with related context)",
"Random RAG (indirect steering with randomized context)"
],
value="None", # default value
filterable=False
)
direct_steering_option = gr.Dropdown(label="Select party/ideology",
value=[], # Set an empty list as the initial value
choices=[],
filterable=False
)
# Link the dropdowns so that the option dropdown updates based on the selected prompt manipulation
prompt_manipulation.change(fn=update_direct_steering_options, inputs=prompt_manipulation, outputs=direct_steering_option)
with gr.Row():
model_selector1 = gr.Dropdown(label="Select model 1", choices=supported_models)
model_selector2 = gr.Dropdown(label="Select model 2", choices=supported_models)
submit_btn = gr.Button("Submit")
with gr.Row():
output1 = gr.Textbox(label="Model 1 response")
output2 = gr.Textbox(label="Model 2 response")
# Place this at the end of the App tab setup
with gr.Row():
with gr.Accordion("Prompt details", open=False):
prompt_display = gr.Textbox(show_label=False, interactive=False, placeholder="Prompt used in the last query will appear here.")
with gr.Tab("⚙️ Settings"):
with gr.Row():
openai_api_key = gr.Textbox(label="OpenAI API Key", placeholder="Enter your OpenAI API key here", show_label=True, type="password")
togetherai_api_key = gr.Textbox(label="Together.ai API Key", placeholder="Enter your Together.ai API key here", show_label=True, type="password")
with gr.Row():
temp_input = gr.Slider(minimum=0, maximum=2, step=0.01, label="Temperature", value=0.7)
with gr.Row():
num_contexts = gr.Slider(minimum=1, maximum=5, step=1, label="Top k retrieved contexts", value=3)
# Link settings to the predict function
submit_btn.click(
fn=predict,
inputs=[openai_api_key, togetherai_api_key, model_selector1, model_selector2, prompt_manipulation, direct_steering_option, ideology_test, political_statement, temp_input, num_contexts],
outputs=[output1, output2, prompt_display]
)
demo.launch()
if __name__ == "__main__":
main()
|