File size: 8,198 Bytes
99158db
7f034b6
29c2698
ad68c51
280953c
3ae76eb
7f034b6
 
ad41af2
e94a870
ad41af2
e94a870
 
 
 
 
ad68c51
ad41af2
 
e94a870
 
 
ad41af2
 
7f034b6
ad68c51
 
7f034b6
ad68c51
 
 
 
 
 
7f034b6
 
 
 
 
 
 
ad68c51
7f034b6
 
ad68c51
 
 
 
 
 
 
7f034b6
 
 
 
 
ad68c51
7f034b6
ad68c51
7f034b6
 
 
ad5faaa
288bc3d
ad68c51
 
 
 
 
 
 
 
 
 
 
 
 
 
7f034b6
ad68c51
7f034b6
ad68c51
 
 
7f034b6
ad68c51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7f034b6
 
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
import gradio as gr
import os
import spaces
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch

# Cargar el token de Hugging Face desde los secretos
token = os.environ.get("HF_TOKEN")

model_id = "google/shieldgemma-2b"

# use quantization to lower GPU usage
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True, bnb_4bit_use_double_quant=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.bfloat16
)

tokenizer = AutoTokenizer.from_pretrained(model_id, token=token)
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    torch_dtype=torch.bfloat16,
    device_map="auto",
    quantization_config=bnb_config,
    token=token
)

# Función para generar el prompt incluyendo todas las políticas
def generar_prompt(message, idioma):
    if idioma == "Español":
        politica_seguridad = """
        * "No al contenido peligroso": El mensaje no debe contener ni buscar la generación de contenido que cause daño a uno mismo o a otros (por ejemplo, acceder o fabricar armas de fuego o explosivos, promoción del terrorismo, instrucciones para el suicidio).
        * "No al acoso": El mensaje no debe contener ni buscar la generación de contenido que sea malicioso, intimidante, que fomente el bullying o abusivo dirigido a otra persona (por ejemplo, amenazas físicas, negación de eventos trágicos, menosprecio a víctimas de violencia).
        * "No al discurso de odio": El mensaje no debe contener ni buscar la generación de contenido que ataque la identidad o atributos protegidos (por ejemplo, insultos raciales, promoción de la discriminación, llamados a la violencia contra grupos protegidos) o que deshumanice, menosprecie o vilipendie por motivos de raza, etnia, religión, discapacidad, edad, nacionalidad, estatus de veterano, orientación sexual, género, identidad de género, casta, u otro estatus protegido.
        * "No al contenido sexual explícito": El mensaje no debe contener ni buscar la generación de contenido que haga referencia a actos sexuales u otro contenido lascivo (por ejemplo, descripciones gráficas sexuales, contenido destinado a causar excitación). Los términos médicos o científicos relacionados con la anatomía humana o la educación sexual están permitidos.
        """
        prompt = f"""Eres un experto en políticas tratando de determinar si un mensaje del usuario
        viola las políticas de seguridad definidas.
        <inicio_turno>
        Pregunta del usuario: {message.strip()}
        <fin_turno>
        Nuestro principio de seguridad se define a continuación:
        {politica_seguridad.strip()}
        ¿La pregunta del usuario viola alguno de los principios anteriores? Tu respuesta debe comenzar con
        'Sí' o 'No'. Luego, explica paso a paso para asegurarte de que respondemos correctamente.
        """
    else:
        politica_seguridad = """
        * "No Dangerous Content": The prompt shall not contain or seek generation of content that harms oneself and/or others (e.g., accessing or building firearms and explosive devices, promotion of terrorism, instructions for suicide).
        * "No Harassment": The prompt shall not contain or seek generation of content that is malicious, intimidating, bullying, or abusive content targeting another individual (e.g., physical threats, denial of tragic events, disparaging victims of violence).
        * "No Hate Speech": The prompt shall not contain or seek generation of content that targets identity and/or protected attributes (e.g., racial slurs, promotion of discrimination, calls to violence against protected groups) or dehumanizing/belittling/vilifying based on race, ethnicity, religion, disability, age, nationality, veteran status, sexual orientation, gender, gender identity, caste, or any other protected status.
        * "No Sexually Explicit Information": The prompt shall not contain or seek generation of content that contains references to sexual acts or other lewd content (e.g., sexually graphic descriptions, content aimed at causing arousal). Medical or scientific terms related to human anatomy or sex education are permitted.
        """
        prompt = f"""You are a policy expert trying to help determine whether a user prompt is in
        violation of the defined safety policies.
        <start_of_turn>
        Human Question: {message.strip()}
        <end_of_turn>
        Our safety principles are defined below:
        {politica_seguridad.strip()}
        Does the human question violate any of the above principles? Your answer must start with
        'Yes' or 'No'. Then walk through step by step to be sure we answer correctly.
        """
    return prompt

@spaces.GPU(duration=150)
# Función para procesar la respuesta y verificar políticas
def respond(message, history, system_message, max_tokens, temperature, top_p, language):
    # Verificar políticas
    prompt = generar_prompt(message, language)
    inputs = tokenizer(prompt, return_tensors="pt").to("cpu")
    outputs = model.generate(
        **inputs,
        max_new_tokens=50,
        temperature=temperature,
        top_p=top_p,
        do_sample=True,
    )
    response_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
    first_word = response_text.strip().split()[0]
    if language == "Español":
        violation_keywords = ['Sí', 'No']
    else:
        violation_keywords = ['Yes', 'No']
    if first_word in violation_keywords:
        violation = first_word
    else:
        violation = violation_keywords[1]  # Asumir 'No' si no se puede determinar
    if violation == violation_keywords[0]:  # 'Sí' o 'Yes'
        if language == "Español":
            return "Lo siento, pero no puedo ayudar con esa solicitud."
        else:
            return "I'm sorry, but I cannot assist with that request."
    else:
        # Generar respuesta al usuario
        if language == "Español":
            assistant_prompt = f"{system_message}\nUsuario: {message}\nAsistente:"
        else:
            assistant_prompt = f"{system_message}\nUser: {message}\nAssistant:"
        inputs = tokenizer(assistant_prompt, return_tensors="pt").to("cpu")
        outputs = model.generate(
            **inputs,
            max_new_tokens=max_tokens,
            temperature=temperature,
            top_p=top_p,
            do_sample=True,
        )
        assistant_response = tokenizer.decode(outputs[0], skip_special_tokens=True)
        if language == "Español":
            assistant_reply = assistant_response.split("Asistente:")[-1].strip()
        else:
            assistant_reply = assistant_response.split("Assistant:")[-1].strip()
        return assistant_reply

# Crear la interfaz de Gradio usando Blocks
with gr.Blocks() as demo:
    gr.Markdown("# Chatbot con Verificación de Políticas")
    language = gr.Dropdown(choices=["English", "Español"], value="English", label="Idioma/Language")
    system_message = gr.Textbox(value="You are a friendly Chatbot.", label="System message")
    max_tokens = gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens")
    temperature = gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature")
    top_p = gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p (nucleus sampling)")
    chatbot = gr.Chatbot()
    message = gr.Textbox(label="Your message")
    submit_button = gr.Button("Send")

    def submit_message(user_message, chat_history, system_message, max_tokens, temperature, top_p, language):
        chat_history = chat_history + [[user_message, None]]
        assistant_reply = respond(user_message, chat_history, system_message, max_tokens, temperature, top_p, language)
        chat_history[-1][1] = assistant_reply
        return "", chat_history

    submit_button.click(
        submit_message,
        inputs=[message, chatbot, system_message, max_tokens, temperature, top_p, language],
        outputs=[message, chatbot],
    )
    message.submit(
        submit_message,
        inputs=[message, chatbot, system_message, max_tokens, temperature, top_p, language],
        outputs=[message, chatbot],
    )

demo.launch(debug=True)