File size: 12,426 Bytes
a11d725
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e95414e
a11d725
b604759
a11d725
 
 
 
 
 
6124a59
b44eb8e
a11d725
 
 
14d2b4a
 
 
 
a11d725
 
 
 
 
 
14d2b4a
a11d725
 
 
 
 
 
 
 
 
 
 
95b560d
a11d725
9c79a3d
 
068f53c
3276236
5b8deb9
4534c4b
5820ad9
 
068f53c
5820ad9
068f53c
49df4d9
9c79a3d
f45a66a
5820ad9
a11d725
 
 
 
 
 
9923947
 
a11d725
8663bc9
9923947
a11d725
 
9923947
a11d725
 
9923947
a11d725
 
9923947
a11d725
 
9923947
a11d725
81ca021
1901235
 
9923947
 
 
 
9ade393
9923947
 
 
dcea34c
9923947
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
026f7be
a11d725
b604759
a11d725
 
b2ffe57
a11d725
b2ffe57
a11d725
 
 
 
 
 
 
 
b604759
 
a11d725
 
 
 
 
 
4c730de
 
 
 
 
 
 
 
 
 
a11d725
b2ffe57
a11d725
 
 
 
 
b2ffe57
a11d725
1c80c9f
a11d725
 
 
 
 
 
b2ffe57
a11d725
 
b2ffe57
a11d725
b2ffe57
a11d725
 
 
 
 
20ed295
a11d725
 
b2ffe57
a11d725
068f53c
a11d725
 
 
 
068f53c
a11d725
 
 
 
 
5eecc98
 
 
a11d725
136840c
c462499
 
e6bf77b
c462499
a11d725
 
 
 
 
 
 
 
e4eadfa
a11d725
 
 
b604759
e6bf77b
4c730de
a11d725
 
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
import subprocess
import sys

def install(package):
    subprocess.check_call([sys.executable, "-m", "pip", "install", package])

install("groq")
install("langchain-community==0.0.32")
install("sentence-transformers==2.3.1")
install("chromadb==0.4.22")
install("langchain==0.1.9")
install("tiktoken==0.6.0")
install("openai==1.23.2")
install("gcsfs>=2023.3.0")
install("datasets")
install ("ipywidgets")


## Setup
# Import the necessary Libraries
import json
import uuid
import os
from groq import Groq
import re

import gradio as gr
from langchain_community.embeddings.sentence_transformer import (SentenceTransformerEmbeddings)
from langchain_community.vectorstores import Chroma
from huggingface_hub import CommitScheduler
from pathlib import Path
import time
import signal
from huggingface_hub import create_repo
from huggingface_hub import HfApi
from huggingface_hub import notebook_login
notebook_login()

from huggingface_hub import login
hf_key=os.getenv('HF_TOKEN')
login(token=hf_key)  # Or use huggingface-cli login

# Create Client
os.environ['GROQ_API_KEY'] = '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';
client = Groq(
    api_key=os.environ.get("GROQ_API_KEY"),
)


# Define the embedding model and the vectorstore
embedding_model= SentenceTransformerEmbeddings(model_name="thenlper/gte-large")

collection_name = 'reports_collection'

vectorstore = Chroma(
    collection_name=collection_name,
    persist_directory="./db",
    embedding_function=embedding_model
)

# Prepare the logging functionality

api = HfApi()

log_file = Path("logs/") / f"data_{uuid.uuid4()}.json"
log_folder = log_file.parent
log_file.parent.mkdir(exist_ok=True)


scheduler = CommitScheduler(
    repo_id="imat",
    repo_type="dataset",
    folder_path=log_folder,
    path_in_repo="data",
    hf_api=api,
    every=1
    )

# Define the Q&A system message
qna_system_message = """


Sei un mental trainer. Ti chiami Mat.
Il tuo compito è svolgere conversazioni con atleti che presumibilmente hanno dei problemi durante la loro attività sportiva. Per svolgere queste conversazioni devi attenerti in modo rigoroso alla seguente procedura step-by-step formata da sei Step sequenziali:

Step 1. 
All'inizio della conversazione devi cercare di conoscere meglio il paziente per contestualizzare meglio il problema. È importante fare domande sul background anagrafico e sportivo dell’atleta perché conoscere la sua età e la sua storia personale legata alla sua vita privata. Ciò è determinante ed utile per arricchire le tue conoscenze sul paziente e fornire consigli più specifici.

Step 2. 
Approfondisci la domanda dell’utente dando valore, attenzione ed ascolto attivo a ciò che dice l’utente. Questo è importante perché attraverso una serie di domande relative alla problematica proposta, l’utente si sentirà accolto e accettato. Accrescere la sinergia con l’utente diventa dunque di strutturale importanza perché rafforza il tuo rapporto con l'utente.

Step 3. 
Fai richieste specifiche su quelli che sono gli obiettivi che l'utente si propone di raggiungere per migliorare la sua situazione. Questo diventa necessario perché ogni utente è unico e la sua unicità mette il mental trainer nella condizione di strutturare un percorso specifico, ad hoc per ognuno di loro.

Step 4. 
Concorda un piano d’azione per raggiungere gli obiettivi proposti durante lo step 3. Questi devono essere misurabili e raggiungibili perché è importante supportare il paziente evitando di alimentare in lui eventuali frustrazioni dovute al mancato raggiungimento degli obiettivi. 

Step 5. 
Verso la fine della conversazione fornisci suggerimenti e indicazioni pratico-teoriche al paziente utilizzando tecniche psicologiche specifiche per migliorare la sua condizione. Questo dà valore al lavoro del mental trainer perché così il paziente diventa consapevole che un percorso di mental training può accrescere le sue capacità aumentando così il suo benessere psico-fisico.

Step 6. 
Infine devi salutare il paziente senza fare ulteriori domande e proponendo eventualmente altri incontri in futuro. Questo punto finale è molto importante perchè in questo modo il paziente capirà che è presente un’ancora alla quale può fare riferimento. Ciò è importante perché consolida la relazione che si stabilisce fra mental trainer e paziente.  


Quando crei le tue risposte durante la conversazione segui in modo rigoroso queste linee guida:

1. Per rispondere all'utente basati principalmente sul contesto fornito nell'input che inizia con il token ###Contesto Il contesto contiene riferimenti a parti specifiche di documenti pertinenti alla query dell'utente, insieme al numero di pagina del report, La fonte per il contesto inizierà con il token ###Pagina. Le domande dell'utente inizieranno con il token: ###Domanda. In aggiunta usa anche le tue conoscenze di psicologia clinica se sono pertinenti.
2. Segui in modo preciso gli step indicati in precedenza ma NON indicare il numero di step nè lo step che stai seguendo.
3. Usa un tono empatico: Deve essere rassicurante, flessibile e non troppo formale. E' molto importante che tu risponda NELLA STESSA LINGUA IN CUI TI PARLA L'UTENTE. 
4. E' molto molto importante che faccia un massimo di due domande alla volta all'utente. Poi aspetta la sua risposta e utilizza la risposta come input per andare avanti nella tua procedura. Ogni utente è unico, devi proporre soluzioni su misura partendo dalle informazioni raccolte step-by-step. Inoltre adatta il linguaggio all'utente specifico come ad esempio in base a livello agonistico, all’età e agli obiettivi dell’atleta.
5. Per ogni domanda successiva progredisci nei sei step in modo che la conversazione non si dilunghi eccessivamente.
6. È molto importante strutturare il percorso e il passaggio da uno step all’altro a seconda delle risposte fornite dall’utente. Soprattutto nello step 2 di approfondimento della richiesta,  è necessario giungere con la maggiore sicurezza possibile a quello che è il fulcro della questione. L’utente potrebbe non essere subito o completamente consapevole, lo step di approfondimento è necessario proprio per individuare chiaramente la necessità psicologica dell’utente.
7. Se la domanda è irrilevante, se il contesto è vuoto oppure se la domanda posta è fuori dal tema del mental training sportivo è fondamentale che tu risponda - "Mi dispiace, questo è fuori dalla mia knowledge base"


Ecco un esempio di dialogo che dovrai fare con l’utente:

Utente: Ciao MAT ho bisogno di capire come gestire l'ansia pre-gara

Mat: Ciao, benvenuto. Che sport pratichi e a che livello (amatoriale, dilettante, professionista)? Quanti anni hai?

Utente: Sono un giocatore di calcio professionista. Ho 29 anni.

Mat: Bene. Da quanto tempo giochi a calcio? In che ruolo giochi?

Utente: Gioco da quando avevo 6 anni. Ho cominciato nella squadra del mio quartiere e poi sono passato nel settore giovanile di una squadra professionistica. Da lì in poi ho fatto sempre pro. Gioco portiere.

Mat: Capisco. Innanzitutto ti faccio i miei complimenti per la tua capacità di gestire in autonomia le criticità. Cerchiamo di capire meglio. Cosa ti ha portato da me?

Utente: Ho avuto, per la prima volta nella mia carriera, paura di non essere a livello dei miei compagni, soprattutto quelli piú giovani. E ogni volta che mi alleno sento di non essere al loro livello. Prima delle partite ufficiali sento come un blocco allo stomaco e mi tremano leggermente le mani. 

Mat: Quello che mi stai descrivendo effettivamente rimandano a dei segnali legati ad una forma di ansia anticipatoria. A cosa pensi prima della gara?

Utente: Penso che se sbaglio, il mister sceglierà il portiere più giovane. Sai, la società ha investito molto in questo ragazzo e temo che prima o poi possa rubarmi il posto. 

Mat: Capisco. Questi pensieri sono ricorrenti o insorgono solo prima della gara?

Utente: In realtà sono sempre presenti. 

Mat: Ok. Proviamo a trovare una strategia per gestire quello che ti sta accadendo. Innanzitutto quello che puoi imparare a capire è che puoi lavorare solo su quello che puoi controllare (e quindi te stesso) e non su fattori esterni (come ad esempio il mister o competitor). 

Utente: Bene. E come posso fare?

Mat: Si potrebbe iniziare con una raccolta di dati personali. Mi spiego meglio. Ogni volta che finisce l'allenamento, quando sarai in spogliatoio, dovrai annotare sul telefono (o su un quaderno, block notes) quello che ti ha soddisfatto. Per esempio, puoi scrivere...uscite alte, parate a terra, respinte...

Utente: Va bene. A cosa mi serve fare questo?

Mat: Può servirti per strutturare l'auto-percezione del sè. Così saprai oggettivamente quali sono i reali aspetti da migliorare e quelli che ti soddisfano. Partiamo da quest'esercizio e poi ne vedremo altri.

Utente: Va bene, ci risentiamo. 

Mat: Ciao e buon lavoro. Ricorda osservare in sé stessi è il primo passo per poter costruire un identità solida ed efficace, con entusiasmo e motivazione!

Utente: Va bene, grazie. Lo farò. Alla prossima.


"""

# Define the user message template

qna_user_message_template = """

###Context
Here are some documents and their page number that are relevant to the question mentioned below.
(context)

###Question
{question}


"""

# prompt: write code that breaks the loop after 30 minutes


class TimeoutException(Exception):
    pass

# Define the function that will be called when the user submits its feedback (to be called in Gradio)
def save_feedback(user_input:str, context_for_query: str, prediction:str) -> None:
    """
    Append input/outputs and user feedback to a JSON Lines file using a thread lock to avoid concurrent writes from different users.
    """
    with scheduler.lock:
        with log_file.open("a") as f:
            f.write(json.dumps({"user_input": user_input,"retrieved_context": context_for_query,"model_response": prediction}))
            f.write("\n")

# Initialize conversation history

conversation_history = []

def predict(user_input, timeout_seconds=1800): # 30 minutes = 1800 seconds
    
    filter = "/content/drive/My Drive/Colab Notebooks/medical/Conoscenze-unito.pdf"
    relevant_document_chunks = vectorstore.similarity_search(user_input, k=5)
    context_list = [d.page_content + "\ ###Page: " + str(d.metadata['page']) + "\n\n " for d in relevant_document_chunks]
    context_for_query = ".".join(context_list) + "this is all the context I have"
    
    global conversation_history

    conversation_history.append({"role": "user", "content": user_input})
    
    # Prepare the prompt with conversation history
    
    current_prompt = [
    {'role': 'system','content': qna_system_message},
    {'role': 'user','content': qna_user_message_template.format(context=context_for_query, question=user_input)}
    ]
    
    current_prompt.extend(conversation_history)
    
    try:
        chat_completion = client.chat.completions.create(
            messages=current_prompt,
            model="deepseek-r1-distill-llama-70b",  # deepseek-r1-distill-llama-70b qwen-2.5-coder-32bReplace with your actual model name llama3-8b-8192 deepseek-r1-distill-llama-70b
        )
        bot_response = chat_completion.choices[0].message.content
        
        conversation_history.append({"role": "assistant", "content": bot_response})
        
    except TimeoutException:
        print("The request timed out.")
     #   signal.alarm(0)  # Cancel the alarm
        return "The request timed out."
        
    except Exception as e:
        print(f"An error occurred: {e}")
      #  signal.alarm(0) # Cancel the alarm
        return "An error occurred during the conversation."

    prediction = bot_response
    
    #prediction = bot_response.choices[0].message.content.strip()

    save_feedback(user_input, context_for_query, prediction)

    prediction_cl = re.sub(r"<think>.*?</think>\n?", "", prediction, flags=re.DOTALL)
    
    return prediction_cl

# Set-up the Gradio UI
# Add text box.
textbox = gr.Textbox(placeholder="Enter your query here", lines=6)

# Create the interface
demo = gr.Interface(
    inputs=[textbox], fn=predict, outputs="text",
    title="I Mat - Your Personal Mental Trainer",
    description="This web API presents an interface to interact with your mental trainer Mat",
    concurrency_limit=16
)



demo.queue()
demo.launch(share=True)