Daniil
commited on
Commit
·
17d7268
1
Parent(s):
dee0ee2
Pushing the repo
Browse files- .gitignore +8 -0
- .streamlit/config.toml +2 -0
- .streamlit/secrets.toml +0 -0
- app.py +149 -0
- environment/environment.yml +166 -0
- pages/FSR_Model.py +944 -0
- pages/FS_Model.py +944 -0
- pages/_2S_Model.py +942 -0
- rag_documents/Isoniazida_Rifapentina.txt +79 -0
- rag_documents/LTBI_PatientBrochure_esp.txt +49 -0
- rag_documents/Preguntas y respuestas sobre la tuberculosis _ TB.txt +509 -0
- rag_documents/Tuberculosis - Diagnóstico y tratamiento - Mayo Clinic.txt +179 -0
- requirements.txt +153 -0
- token_generator.py +13 -0
- utils/RAG_utils.py +59 -0
- utils/convo_utils.py +31 -0
- utils/prompt_utils.py +197 -0
.gitignore
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# compiled python
|
2 |
+
*.pyc
|
3 |
+
# PDF
|
4 |
+
*.pdf
|
5 |
+
# Pickled files
|
6 |
+
*.pkl
|
7 |
+
|
8 |
+
*.json
|
.streamlit/config.toml
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
[server]
|
2 |
+
headless = true
|
.streamlit/secrets.toml
ADDED
File without changes
|
app.py
ADDED
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import os
|
3 |
+
import random
|
4 |
+
import importlib.util
|
5 |
+
import firebase_admin
|
6 |
+
from firebase_admin import credentials, firestore
|
7 |
+
|
8 |
+
|
9 |
+
# Initialize Firebase
|
10 |
+
if not firebase_admin._apps:
|
11 |
+
cred = credentials.Certificate("coco-evaluation-firebase-adminsdk-p3m64-99c4ea22c1.json")
|
12 |
+
firebase_admin.initialize_app(cred)
|
13 |
+
db = firestore.client()
|
14 |
+
|
15 |
+
|
16 |
+
# Set page configuration as the first command
|
17 |
+
st.set_page_config(
|
18 |
+
page_title="TB Chatbot Evaluation",
|
19 |
+
page_icon="👋",
|
20 |
+
)
|
21 |
+
|
22 |
+
|
23 |
+
# tesing again
|
24 |
+
|
25 |
+
|
26 |
+
# Set passcode for authentication
|
27 |
+
PASSCODE = os.environ["MY_PASSCODE"]
|
28 |
+
|
29 |
+
# Initialize authentication state
|
30 |
+
if "authenticated" not in st.session_state:
|
31 |
+
st.session_state["authenticated"] = False
|
32 |
+
|
33 |
+
|
34 |
+
# Initialize session state variables
|
35 |
+
def init_session_state():
|
36 |
+
if "authenticated" not in st.session_state:
|
37 |
+
st.session_state["authenticated"] = False
|
38 |
+
if "evaluator_confirmed" not in st.session_state:
|
39 |
+
st.session_state["evaluator_confirmed"] = None
|
40 |
+
if "model_order" not in st.session_state:
|
41 |
+
st.session_state["model_order"] = []
|
42 |
+
if "current_index" not in st.session_state:
|
43 |
+
st.session_state["current_index"] = 0
|
44 |
+
if "models_completed" not in st.session_state:
|
45 |
+
st.session_state["models_completed"] = False
|
46 |
+
if "evaluation_status" not in st.session_state or not st.session_state["evaluation_status"]:
|
47 |
+
st.session_state["evaluation_status"] = {}
|
48 |
+
if "all_evaluations" not in st.session_state:
|
49 |
+
st.session_state["all_evaluations"] = {}
|
50 |
+
if "evaluation_ids" not in st.session_state:
|
51 |
+
st.session_state["evaluation_ids"] = {}
|
52 |
+
if "start_time" not in st.session_state:
|
53 |
+
st.session_state["start_time"] = None
|
54 |
+
if "evaluation_durations" not in st.session_state:
|
55 |
+
st.session_state["evaluation_durations"] = {}
|
56 |
+
if "submitted_evaluations" not in st.session_state:
|
57 |
+
st.session_state["submitted_evaluations"] = set()
|
58 |
+
|
59 |
+
|
60 |
+
init_session_state()
|
61 |
+
|
62 |
+
|
63 |
+
# Display Welcome Page
|
64 |
+
if not st.session_state["authenticated"]:
|
65 |
+
st.markdown(f"<h1 style='text-align: center;'>Welcome to the TB Chatbot Evaluation</h1>", unsafe_allow_html=True)
|
66 |
+
|
67 |
+
col1, col2, col3 = st.columns([2, 1, 1])
|
68 |
+
with col1:
|
69 |
+
st.write("Are you an evaluator?")
|
70 |
+
with col2:
|
71 |
+
if st.button("Yes"):
|
72 |
+
st.session_state["evaluator_confirmed"] = True
|
73 |
+
with col3:
|
74 |
+
if st.button("No"):
|
75 |
+
st.session_state["evaluator_confirmed"] = False
|
76 |
+
|
77 |
+
if st.session_state["evaluator_confirmed"]:
|
78 |
+
evaluator_id = st.text_input("Enter your Evaluator ID (can be anything)")
|
79 |
+
passcode = st.text_input("Enter Passcode to Access Models (password is the same)", type="password")
|
80 |
+
if st.button("Submit"):
|
81 |
+
print("Hello")
|
82 |
+
if passcode == PASSCODE and evaluator_id:
|
83 |
+
print("Submitted")
|
84 |
+
# Save Evaluator ID
|
85 |
+
db.collection("evaluator_ids").document(evaluator_id).set({
|
86 |
+
"evaluator_id": evaluator_id,
|
87 |
+
"timestamp": firestore.SERVER_TIMESTAMP
|
88 |
+
})
|
89 |
+
|
90 |
+
# Update session state
|
91 |
+
st.session_state["authenticated"] = True
|
92 |
+
st.session_state["evaluator_id"] = evaluator_id
|
93 |
+
|
94 |
+
|
95 |
+
# Show the main content only if authenticated
|
96 |
+
if st.session_state["authenticated"]:
|
97 |
+
# Sidebar with only randomized page navigation
|
98 |
+
with st.sidebar:
|
99 |
+
# Only create the page mapping if it doesn't already exist in the session state
|
100 |
+
if "page_mapping" not in st.session_state:
|
101 |
+
# Get list of page files and randomize their order
|
102 |
+
PAGES_DIR = "pages"
|
103 |
+
page_files = [f for f in os.listdir(PAGES_DIR) if f.endswith(".py")]
|
104 |
+
random.shuffle(page_files)
|
105 |
+
|
106 |
+
# Create generic names for display
|
107 |
+
generic_names = [f"Model {chr(65 + i)}" for i in range(len(page_files))]
|
108 |
+
|
109 |
+
# Create a dictionary to map display names to file paths
|
110 |
+
st.session_state["page_mapping"] = {
|
111 |
+
generic_name: os.path.join(PAGES_DIR, page_file) for generic_name, page_file in zip(generic_names, page_files)
|
112 |
+
}
|
113 |
+
|
114 |
+
# Retrieve the consistent mapping from session state
|
115 |
+
pages = st.session_state["page_mapping"]
|
116 |
+
|
117 |
+
# Sidebar navigation selectbox with generic labels
|
118 |
+
selected_generic_name = st.selectbox("Navigation", list(pages.keys()), label_visibility="collapsed")
|
119 |
+
|
120 |
+
# Load and run the selected page dynamically using the selected generic name
|
121 |
+
selected_page_path = pages[selected_generic_name]
|
122 |
+
spec = importlib.util.spec_from_file_location(selected_generic_name, selected_page_path)
|
123 |
+
module = importlib.util.module_from_spec(spec)
|
124 |
+
spec.loader.exec_module(module)
|
125 |
+
|
126 |
+
# Display main welcome message
|
127 |
+
st.markdown("""
|
128 |
+
# Welcome to the TB Chatbot Simulation Portal
|
129 |
+
|
130 |
+
This portal allows you to interact with our TB-powered chatbot, built using OpenAI's GPT-4. Here, you can evaluate multiple chatbot configurations, each designed to foster trust, empathy, and medical accuracy in responses.
|
131 |
+
|
132 |
+
## Purpose
|
133 |
+
|
134 |
+
Your task is to assess the chatbot models by interacting with them using patient scenario-based questions. Evaluate each model based on the following principles:
|
135 |
+
|
136 |
+
### Trust
|
137 |
+
- Does the response convey confidence and reliability?
|
138 |
+
- Are the answers factually accurate and rooted in medical expertise?
|
139 |
+
|
140 |
+
### Medical Accuracy
|
141 |
+
- Are responses aligned with current medical guidelines and best practices?
|
142 |
+
- Do they avoid misinformation or potentially harmful suggestions?
|
143 |
+
|
144 |
+
### Empathy
|
145 |
+
- Does the chatbot demonstrate understanding and compassion?
|
146 |
+
- Are responses emotionally sensitive and supportive?
|
147 |
+
|
148 |
+
Your feedback will help us identify the best model to support our mission of enhancing patient communication and care through AI-driven solutions.
|
149 |
+
""")
|
environment/environment.yml
ADDED
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
name: streamlit-env
|
2 |
+
channels:
|
3 |
+
- defaults
|
4 |
+
dependencies:
|
5 |
+
- ca-certificates=2024.9.24
|
6 |
+
- libcxx=14.0.6
|
7 |
+
- libffi=3.4.4
|
8 |
+
- ncurses=6.4
|
9 |
+
- openssl=3.0.15
|
10 |
+
- pip=24.2
|
11 |
+
- python=3.9.20
|
12 |
+
- readline=8.2
|
13 |
+
- setuptools=75.1.0
|
14 |
+
- sqlite=3.45.3
|
15 |
+
- tk=8.6.14
|
16 |
+
- wheel=0.44.0
|
17 |
+
- xz=5.4.6
|
18 |
+
- zlib=1.2.13
|
19 |
+
- pip:
|
20 |
+
- aiohappyeyeballs==2.4.3
|
21 |
+
- aiohttp==3.10.10
|
22 |
+
- aiosignal==1.3.1
|
23 |
+
- altair==5.4.1
|
24 |
+
- annotated-types==0.7.0
|
25 |
+
- anyio==4.6.2.post1
|
26 |
+
- asgiref==3.8.1
|
27 |
+
- async-timeout==4.0.3
|
28 |
+
- attrs==24.2.0
|
29 |
+
- backoff==2.2.1
|
30 |
+
- bcrypt==4.2.0
|
31 |
+
- blinker==1.8.2
|
32 |
+
- build==1.2.2.post1
|
33 |
+
- cachetools==5.5.0
|
34 |
+
- certifi==2024.8.30
|
35 |
+
- charset-normalizer==3.4.0
|
36 |
+
- chroma-hnswlib==0.7.6
|
37 |
+
- chromadb==0.5.15
|
38 |
+
- click==8.1.7
|
39 |
+
- coloredlogs==15.0.1
|
40 |
+
- dataclasses-json==0.6.7
|
41 |
+
- deprecated==1.2.14
|
42 |
+
- distro==1.9.0
|
43 |
+
- durationpy==0.9
|
44 |
+
- exceptiongroup==1.2.2
|
45 |
+
- fastapi==0.115.3
|
46 |
+
- filelock==3.16.1
|
47 |
+
- flatbuffers==24.3.25
|
48 |
+
- frozenlist==1.5.0
|
49 |
+
- fsspec==2024.10.0
|
50 |
+
- gitdb==4.0.11
|
51 |
+
- gitpython==3.1.43
|
52 |
+
- google-auth==2.35.0
|
53 |
+
- googleapis-common-protos==1.65.0
|
54 |
+
- grpcio==1.67.0
|
55 |
+
- h11==0.14.0
|
56 |
+
- httpcore==1.0.6
|
57 |
+
- httptools==0.6.4
|
58 |
+
- httpx==0.27.2
|
59 |
+
- huggingface-hub==0.26.1
|
60 |
+
- humanfriendly==10.0
|
61 |
+
- idna==3.10
|
62 |
+
- importlib-metadata==8.4.0
|
63 |
+
- importlib-resources==6.4.5
|
64 |
+
- jinja2==3.1.4
|
65 |
+
- jiter==0.6.1
|
66 |
+
- joblib==1.4.2
|
67 |
+
- jsonpatch==1.33
|
68 |
+
- jsonpointer==3.0.0
|
69 |
+
- jsonschema==4.23.0
|
70 |
+
- jsonschema-specifications==2024.10.1
|
71 |
+
- kubernetes==31.0.0
|
72 |
+
- langchain==0.3.4
|
73 |
+
- langchain-community==0.3.3
|
74 |
+
- langchain-core==0.3.13
|
75 |
+
- langchain-huggingface==0.1.0
|
76 |
+
- langchain-text-splitters==0.3.0
|
77 |
+
- langsmith==0.1.137
|
78 |
+
- markdown-it-py==3.0.0
|
79 |
+
- markupsafe==3.0.2
|
80 |
+
- marshmallow==3.23.0
|
81 |
+
- mdurl==0.1.2
|
82 |
+
- mmh3==5.0.1
|
83 |
+
- monotonic==1.6
|
84 |
+
- mpmath==1.3.0
|
85 |
+
- multidict==6.1.0
|
86 |
+
- mypy-extensions==1.0.0
|
87 |
+
- narwhals==1.10.0
|
88 |
+
- networkx==3.2.1
|
89 |
+
- numpy==1.26.4
|
90 |
+
- oauthlib==3.2.2
|
91 |
+
- onnxruntime==1.19.2
|
92 |
+
- openai==1.52.2
|
93 |
+
- opentelemetry-api==1.27.0
|
94 |
+
- opentelemetry-exporter-otlp-proto-common==1.27.0
|
95 |
+
- opentelemetry-exporter-otlp-proto-grpc==1.27.0
|
96 |
+
- opentelemetry-instrumentation==0.48b0
|
97 |
+
- opentelemetry-instrumentation-asgi==0.48b0
|
98 |
+
- opentelemetry-instrumentation-fastapi==0.48b0
|
99 |
+
- opentelemetry-proto==1.27.0
|
100 |
+
- opentelemetry-sdk==1.27.0
|
101 |
+
- opentelemetry-semantic-conventions==0.48b0
|
102 |
+
- opentelemetry-util-http==0.48b0
|
103 |
+
- orjson==3.10.10
|
104 |
+
- overrides==7.7.0
|
105 |
+
- packaging==24.1
|
106 |
+
- pandas==2.2.3
|
107 |
+
- pillow==10.4.0
|
108 |
+
- posthog==3.7.0
|
109 |
+
- propcache==0.2.0
|
110 |
+
- protobuf==4.25.5
|
111 |
+
- pyarrow==17.0.0
|
112 |
+
- pyasn1==0.6.1
|
113 |
+
- pyasn1-modules==0.4.1
|
114 |
+
- pydantic==2.9.2
|
115 |
+
- pydantic-core==2.23.4
|
116 |
+
- pydantic-settings==2.6.0
|
117 |
+
- pydeck==0.9.1
|
118 |
+
- pygments==2.18.0
|
119 |
+
- pypika==0.48.9
|
120 |
+
- pyproject-hooks==1.2.0
|
121 |
+
- python-dateutil==2.9.0.post0
|
122 |
+
- python-dotenv==1.0.1
|
123 |
+
- pytz==2024.2
|
124 |
+
- pyyaml==6.0.2
|
125 |
+
- referencing==0.35.1
|
126 |
+
- regex==2024.9.11
|
127 |
+
- requests==2.32.3
|
128 |
+
- requests-oauthlib==2.0.0
|
129 |
+
- requests-toolbelt==1.0.0
|
130 |
+
- rich==13.9.3
|
131 |
+
- rpds-py==0.20.0
|
132 |
+
- rsa==4.9
|
133 |
+
- safetensors==0.4.5
|
134 |
+
- scikit-learn==1.5.2
|
135 |
+
- scipy==1.13.1
|
136 |
+
- sentence-transformers==3.2.1
|
137 |
+
- shellingham==1.5.4
|
138 |
+
- six==1.16.0
|
139 |
+
- smmap==5.0.1
|
140 |
+
- sniffio==1.3.1
|
141 |
+
- sqlalchemy==2.0.36
|
142 |
+
- starlette==0.41.0
|
143 |
+
- streamlit==1.39.0
|
144 |
+
- sympy==1.13.1
|
145 |
+
- tenacity==9.0.0
|
146 |
+
- threadpoolctl==3.5.0
|
147 |
+
- tokenizers==0.20.1
|
148 |
+
- toml==0.10.2
|
149 |
+
- tomli==2.0.2
|
150 |
+
- torch==2.5.0
|
151 |
+
- tornado==6.4.1
|
152 |
+
- tqdm==4.66.5
|
153 |
+
- transformers==4.46.0
|
154 |
+
- typer==0.12.5
|
155 |
+
- typing-extensions==4.12.2
|
156 |
+
- typing-inspect==0.9.0
|
157 |
+
- tzdata==2024.2
|
158 |
+
- urllib3==2.2.3
|
159 |
+
- uvicorn==0.32.0
|
160 |
+
- uvloop==0.21.0
|
161 |
+
- watchfiles==0.24.0
|
162 |
+
- websocket-client==1.8.0
|
163 |
+
- websockets==13.1
|
164 |
+
- wrapt==1.16.0
|
165 |
+
- yarl==1.16.0
|
166 |
+
- zipp==3.20.2
|
pages/FSR_Model.py
ADDED
@@ -0,0 +1,944 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import uuid
|
2 |
+
import streamlit as st
|
3 |
+
from openai import AzureOpenAI
|
4 |
+
import firebase_admin
|
5 |
+
from firebase_admin import credentials, firestore
|
6 |
+
from typing import Dict, Any
|
7 |
+
import time
|
8 |
+
import os
|
9 |
+
import tempfile
|
10 |
+
import json
|
11 |
+
|
12 |
+
from utils.prompt_utils import PERSONA_PREFIX, baseline, baseline_esp, fs, RAG, EMOTIONAL_PROMPT, CLASSIFICATION_PROMPT, INFORMATIONAL_PROMPT
|
13 |
+
from utils.RAG_utils import load_or_create_vectorstore
|
14 |
+
|
15 |
+
# PERSONA_PREFIX = ""
|
16 |
+
# baseline = ""
|
17 |
+
# baseline_esp = ""
|
18 |
+
# fs = ""
|
19 |
+
# RAG = ""
|
20 |
+
# EMOTIONAL_PROMPT = ""
|
21 |
+
# CLASSIFICATION_PROMPT = """
|
22 |
+
# Determine si esta afirmación busca empatía o (1) o busca información (0).
|
23 |
+
# Clasifique como emocional sólo si la pregunta expresa preocupación, ansiedad o malestar sobre el estado de salud del paciente.
|
24 |
+
# En caso contrario, clasificar como informativo.
|
25 |
+
|
26 |
+
# Ejemplos:
|
27 |
+
# - Pregunta: Me siento muy ansioso por mi diagnóstico de tuberculosis. 1
|
28 |
+
# - Pregunta: ¿Cuáles son los efectos secundarios comunes de los medicamentos contra la tuberculosis? 0
|
29 |
+
# - Pregunta: Estoy preocupada porque tengo mucho dolor. 1
|
30 |
+
# - Pregunta: ¿Es seguro tomar medicamentos como analgésicos junto con medicamentos para la tuberculosis? 0
|
31 |
+
|
32 |
+
# Aquí está la declaración para clasificar. Simplemente responda con el número "1" o "0":
|
33 |
+
# """
|
34 |
+
|
35 |
+
# INFORMATIONAL_PROMPT = ""
|
36 |
+
|
37 |
+
# Model configurations remain the same
|
38 |
+
MODEL_CONFIGS = {
|
39 |
+
# "Model 0: Naive English Baseline Model": {
|
40 |
+
# "name": "Model 0: Naive English Baseline Model",
|
41 |
+
# "prompt": PERSONA_PREFIX + baseline,
|
42 |
+
# "uses_rag": False,
|
43 |
+
# "uses_classification": False
|
44 |
+
# },
|
45 |
+
# "Model 1: Naive Spanish Baseline Model": {
|
46 |
+
# "name": "Model 1: Baseline Model",
|
47 |
+
# "prompt": PERSONA_PREFIX + baseline_esp,
|
48 |
+
# "uses_rag": False,
|
49 |
+
# "uses_classification": False
|
50 |
+
# },
|
51 |
+
# "Model 1": {
|
52 |
+
# "name": "Model 1: Few_Shot model",
|
53 |
+
# "prompt": PERSONA_PREFIX + fs,
|
54 |
+
# "uses_rag": False,
|
55 |
+
# "uses_classification": False
|
56 |
+
# },
|
57 |
+
# "Model 3: RAG Model": {F
|
58 |
+
# "name": "Model 3: RAG Model",
|
59 |
+
# "prompt": PERSONA_PREFIX + RAG,
|
60 |
+
# "uses_rag": True,
|
61 |
+
# "uses_classification": False
|
62 |
+
# },
|
63 |
+
"Model 2": {
|
64 |
+
"name": "Model 2: RAG + Few_Shot Model",
|
65 |
+
"prompt": PERSONA_PREFIX + RAG + fs,
|
66 |
+
"uses_rag": True,
|
67 |
+
"uses_classification": False
|
68 |
+
},
|
69 |
+
# "Model 3": {
|
70 |
+
# "name": "Model 3: 2-Stage Classification Model",
|
71 |
+
# "prompt": PERSONA_PREFIX + INFORMATIONAL_PROMPT, # default
|
72 |
+
# "uses_rag": False,
|
73 |
+
# "uses_classification": False
|
74 |
+
# },
|
75 |
+
# "Model 6: Multi-Agent": {
|
76 |
+
# "name": "Model 6: Multi-Agent",
|
77 |
+
# "prompt": PERSONA_PREFIX + INFORMATIONAL_PROMPT, # default
|
78 |
+
# "uses_rag": True,
|
79 |
+
# "uses_classification": True,
|
80 |
+
# "uses_judges": True
|
81 |
+
# }
|
82 |
+
}
|
83 |
+
PASSCODE = os.environ["MY_PASSCODE"]
|
84 |
+
|
85 |
+
# # Authentication check
|
86 |
+
# if "authenticated" not in st.session_state or not st.session_state["authenticated"]:
|
87 |
+
# st.error("Access denied. Please go back to the main page and enter the passcode.")
|
88 |
+
# st.stop()
|
89 |
+
|
90 |
+
# Initialize Firebase
|
91 |
+
if not firebase_admin._apps:
|
92 |
+
cred = credentials.Certificate("coco-evaluation-firebase-adminsdk-p3m64-99c4ea22c1.json")
|
93 |
+
firebase_admin.initialize_app(cred)
|
94 |
+
db = firestore.client()
|
95 |
+
|
96 |
+
endpoint = os.environ["ENDPOINT_URL"]
|
97 |
+
deployment = os.environ["DEPLOYMENT"]
|
98 |
+
subscription_key = os.environ["subscription_key"]
|
99 |
+
|
100 |
+
# OpenAI API setup
|
101 |
+
client = AzureOpenAI(
|
102 |
+
azure_endpoint=endpoint,
|
103 |
+
api_key=subscription_key,
|
104 |
+
api_version=os.environ["api_version"]
|
105 |
+
)
|
106 |
+
|
107 |
+
def authenticate():
|
108 |
+
creds_dict = {
|
109 |
+
"type": os.environ.get("FIREBASE_TYPE", "service_account"),
|
110 |
+
"project_id": os.environ.get("FIREBASE_PROJECT_ID"),
|
111 |
+
"private_key_id": os.environ.get("FIREBASE_PRIVATE_KEY_ID"),
|
112 |
+
"private_key": os.environ.get("FIREBASE_PRIVATE_KEY", "").replace("\\n", "\n"),
|
113 |
+
"client_email": os.environ.get("FIREBASE_CLIENT_EMAIL"),
|
114 |
+
"client_id": os.environ.get("FIREBASE_CLIENT_ID"),
|
115 |
+
"auth_uri": os.environ.get("FIREBASE_AUTH_URI", "https://accounts.google.com/o/oauth2/auth"),
|
116 |
+
"token_uri": os.environ.get("FIREBASE_TOKEN_URI", "https://oauth2.googleapis.com/token"),
|
117 |
+
"auth_provider_x509_cert_url": os.environ.get("FIREBASE_AUTH_PROVIDER_X509_CERT_URL",
|
118 |
+
"https://www.googleapis.com/oauth2/v1/certs"),
|
119 |
+
"client_x509_cert_url": os.environ.get("FIREBASE_CLIENT_X509_CERT_URL"),
|
120 |
+
"universe_domain": "googleapis.com"
|
121 |
+
|
122 |
+
}
|
123 |
+
# Create a temporary JSON file
|
124 |
+
with tempfile.NamedTemporaryFile(suffix='.json', delete=False, mode='w') as temp_file:
|
125 |
+
json.dump(creds_dict, temp_file)
|
126 |
+
temp_file.close()
|
127 |
+
|
128 |
+
import uuid
|
129 |
+
|
130 |
+
random_id = uuid.uuid4()
|
131 |
+
random_id_string = str(random_id)
|
132 |
+
evaluator_id = random_id_string
|
133 |
+
db = firestore.client()
|
134 |
+
db.collection("evaluator_ids").document(evaluator_id).set({
|
135 |
+
"evaluator_id": evaluator_id,
|
136 |
+
"timestamp": firestore.SERVER_TIMESTAMP
|
137 |
+
})
|
138 |
+
|
139 |
+
# Update session state
|
140 |
+
st.session_state["authenticated"] = True
|
141 |
+
st.session_state["evaluator_id"] = evaluator_id
|
142 |
+
|
143 |
+
def init():
|
144 |
+
"""Initialize all necessary components and state variables"""
|
145 |
+
# Initialize Firebase if not already initialized
|
146 |
+
if not firebase_admin._apps:
|
147 |
+
cred = credentials.Certificate("coco-evaluation-firebase-adminsdk-p3m64-99c4ea22c1.json")
|
148 |
+
firebase_admin.initialize_app(cred)
|
149 |
+
|
150 |
+
# Initialize session state variables
|
151 |
+
if "messages" not in st.session_state:
|
152 |
+
st.session_state.messages = {}
|
153 |
+
if "session_id" not in st.session_state:
|
154 |
+
st.session_state.session_id = str(uuid.uuid4())
|
155 |
+
if "chat_active" not in st.session_state:
|
156 |
+
st.session_state.chat_active = False
|
157 |
+
if "user_input" not in st.session_state:
|
158 |
+
st.session_state.user_input = ""
|
159 |
+
if "user_id" not in st.session_state:
|
160 |
+
st.session_state.user_id = f"anonymous_{str(uuid.uuid4())}"
|
161 |
+
if "selected_model" not in st.session_state:
|
162 |
+
st.session_state.selected_model = list(MODEL_CONFIGS.keys())[0]
|
163 |
+
if "model_profile" not in st.session_state:
|
164 |
+
st.session_state.model_profile = [0, 0]
|
165 |
+
|
166 |
+
# Load vectorstore at startup
|
167 |
+
if "vectorstore" not in st.session_state:
|
168 |
+
with st.spinner("Loading document embeddings..."):
|
169 |
+
st.session_state.vectorstore = load_or_create_vectorstore()
|
170 |
+
|
171 |
+
def get_classification(client, deployment, user_input):
|
172 |
+
"""Classify the input as emotional (1) or informational (0)"""
|
173 |
+
chat_prompt = [
|
174 |
+
{"role": "system", "content": CLASSIFICATION_PROMPT},
|
175 |
+
{"role": "user", "content": user_input}
|
176 |
+
]
|
177 |
+
|
178 |
+
completion = client.chat.completions.create(
|
179 |
+
model=deployment,
|
180 |
+
messages=chat_prompt,
|
181 |
+
max_tokens=1,
|
182 |
+
temperature=0,
|
183 |
+
top_p=0.9,
|
184 |
+
frequency_penalty=0,
|
185 |
+
presence_penalty=0,
|
186 |
+
stop=None
|
187 |
+
)
|
188 |
+
|
189 |
+
return completion.choices[0].message.content.strip()
|
190 |
+
def process_input():
|
191 |
+
try:
|
192 |
+
current_model = st.session_state.selected_model
|
193 |
+
user_input = st.session_state.user_input
|
194 |
+
|
195 |
+
if not user_input.strip():
|
196 |
+
st.warning("Please enter a message before sending.")
|
197 |
+
return
|
198 |
+
|
199 |
+
model_config = MODEL_CONFIGS.get(current_model)
|
200 |
+
if not model_config:
|
201 |
+
st.error("Invalid model selected. Please choose a valid model.")
|
202 |
+
return
|
203 |
+
|
204 |
+
if current_model not in st.session_state.messages:
|
205 |
+
st.session_state.messages[current_model] = []
|
206 |
+
|
207 |
+
st.session_state.messages[current_model].append({"role": "user", "content": user_input})
|
208 |
+
|
209 |
+
try:
|
210 |
+
log_message("user", user_input)
|
211 |
+
except Exception as e:
|
212 |
+
st.warning(f"Failed to log message: {str(e)}")
|
213 |
+
|
214 |
+
conversation_history = "\n".join([f"{msg['role'].capitalize()}: {msg['content']}"
|
215 |
+
for msg in st.session_state.messages[current_model]])
|
216 |
+
|
217 |
+
# Helper function for error handling in API calls
|
218 |
+
def safe_api_call(messages, max_retries=3):
|
219 |
+
for attempt in range(max_retries):
|
220 |
+
try:
|
221 |
+
response = client.chat.completions.create(
|
222 |
+
model=deployment,
|
223 |
+
messages=messages,
|
224 |
+
max_tokens=3500,
|
225 |
+
temperature=0.1,
|
226 |
+
top_p=0.9
|
227 |
+
)
|
228 |
+
return response.choices[0].message.content.strip()
|
229 |
+
except Exception as e:
|
230 |
+
if attempt == max_retries - 1:
|
231 |
+
raise Exception(f"Failed to get response after {max_retries} attempts: {str(e)}")
|
232 |
+
st.warning(f"Attempt {attempt + 1} failed, retrying...")
|
233 |
+
time.sleep(1)
|
234 |
+
|
235 |
+
def perform_rag_query(input_text, conversation_history):
|
236 |
+
try:
|
237 |
+
relevant_docs = retrieve_relevant_documents(
|
238 |
+
st.session_state.vectorstore,
|
239 |
+
input_text,
|
240 |
+
conversation_history,
|
241 |
+
client=client
|
242 |
+
)
|
243 |
+
|
244 |
+
model_messages = [
|
245 |
+
{"role": "system", "content": f"{model_config['prompt']}\n\nContexto: {relevant_docs}"}
|
246 |
+
] + st.session_state.messages[current_model]
|
247 |
+
|
248 |
+
return safe_api_call(model_messages), relevant_docs
|
249 |
+
|
250 |
+
except Exception as e:
|
251 |
+
st.error(f"Error in RAG query: {str(e)}")
|
252 |
+
return "Lo siento, hubo un error al procesar tu consulta. Por favor, intenta nuevamente.", ""
|
253 |
+
|
254 |
+
initial_response = None
|
255 |
+
initial_docs = ""
|
256 |
+
|
257 |
+
# Handle 2-stage model
|
258 |
+
if model_config.get('uses_classification', False):
|
259 |
+
try:
|
260 |
+
classification = get_classification(client, deployment, user_input)
|
261 |
+
|
262 |
+
if 'classifications' not in st.session_state:
|
263 |
+
st.session_state.classifications = {}
|
264 |
+
st.session_state.classifications[len(st.session_state.messages[current_model]) - 1] = classification
|
265 |
+
|
266 |
+
if classification == "0":
|
267 |
+
initial_response, initial_docs = perform_rag_query(user_input, conversation_history)
|
268 |
+
else:
|
269 |
+
model_messages = [
|
270 |
+
{"role": "system", "content": PERSONA_PREFIX + EMOTIONAL_PROMPT}
|
271 |
+
] + st.session_state.messages[current_model]
|
272 |
+
initial_response = safe_api_call(model_messages)
|
273 |
+
|
274 |
+
except Exception as e:
|
275 |
+
st.error(f"Error in classification stage: {str(e)}")
|
276 |
+
initial_response = "Lo siento, hubo un error al procesar tu consulta. Por favor, intenta nuevamente."
|
277 |
+
|
278 |
+
# Handle RAG models
|
279 |
+
if model_config.get('uses_rag', False):
|
280 |
+
try:
|
281 |
+
if not initial_response:
|
282 |
+
initial_response, initial_docs = perform_rag_query(user_input, conversation_history)
|
283 |
+
|
284 |
+
verification_docs = retrieve_relevant_documents(
|
285 |
+
st.session_state.vectorstore,
|
286 |
+
initial_response,
|
287 |
+
conversation_history,
|
288 |
+
client=client
|
289 |
+
)
|
290 |
+
|
291 |
+
combined_docs = initial_docs + "\nContexto de verificación adicional:\n" + verification_docs
|
292 |
+
|
293 |
+
verification_messages = [
|
294 |
+
{
|
295 |
+
"role": "system",
|
296 |
+
"content": f"Pregunta del paciente:{user_input} \nContexto: {combined_docs} \nRespuesta anterior: {initial_response}\n Verifique la precisión médica de la respuesta anterior y refine la respuesta según el contexto adicional."
|
297 |
+
}
|
298 |
+
]
|
299 |
+
|
300 |
+
assistant_reply = safe_api_call(verification_messages)
|
301 |
+
|
302 |
+
except Exception as e:
|
303 |
+
st.error(f"Error in RAG processing: {str(e)}")
|
304 |
+
assistant_reply = "Lo siento, hubo un error al procesar tu consulta. Por favor, intenta nuevamente."
|
305 |
+
else:
|
306 |
+
try:
|
307 |
+
model_messages = [
|
308 |
+
{"role": "system", "content": model_config['prompt']}
|
309 |
+
] + st.session_state.messages[current_model]
|
310 |
+
|
311 |
+
assistant_reply = safe_api_call(model_messages)
|
312 |
+
|
313 |
+
except Exception as e:
|
314 |
+
st.error(f"Error generating response: {str(e)}")
|
315 |
+
assistant_reply = "Lo siento, hubo un error al procesar tu consulta. Por favor, intenta nuevamente."
|
316 |
+
|
317 |
+
# Store and log the final response
|
318 |
+
try:
|
319 |
+
st.session_state.messages[current_model].append({"role": "assistant", "content": assistant_reply})
|
320 |
+
log_message("assistant", assistant_reply)
|
321 |
+
# store_conversation_data()
|
322 |
+
except Exception as e:
|
323 |
+
st.warning(f"Failed to store or log response: {str(e)}")
|
324 |
+
|
325 |
+
st.session_state.user_input = ""
|
326 |
+
|
327 |
+
except Exception as e:
|
328 |
+
st.error(f"An unexpected error occurred: {str(e)}")
|
329 |
+
st.session_state.user_input = ""
|
330 |
+
|
331 |
+
|
332 |
+
def check_document_relevance(query, doc, client):
|
333 |
+
"""
|
334 |
+
Check document relevance using few-shot prompting for Spanish TB context.
|
335 |
+
|
336 |
+
Args:
|
337 |
+
query (str): The user's input query
|
338 |
+
doc (str): The retrieved document text
|
339 |
+
client: The OpenAI client instance
|
340 |
+
|
341 |
+
Returns:
|
342 |
+
bool: True if document is relevant, False otherwise
|
343 |
+
"""
|
344 |
+
few_shot_prompt = f"""Determine si el documento es relevante para la consulta sobre tuberculosis.
|
345 |
+
Responde únicamente 'sí' si es relevante o 'no' si no es relevante.
|
346 |
+
Ejemplos:
|
347 |
+
Consulta: ¿Cuáles son los efectos secundarios de la rifampicina?
|
348 |
+
Documento: La rifampicina puede causar efectos secundarios como náuseas, vómitos y coloración naranja de fluidos corporales. Es importante tomar el medicamento con el estómago vacío.
|
349 |
+
Respuesta: sí
|
350 |
+
Consulta: ¿Cuánto dura el tratamiento de TB?
|
351 |
+
Documento: El dengue es una enfermedad viral transmitida por mosquitos. Los síntomas incluyen fiebre alta y dolor muscular.
|
352 |
+
Respuesta: no
|
353 |
+
Consulta: ¿Cómo se realiza la prueba de esputo?
|
354 |
+
Documento: Para la prueba de esputo, el paciente debe toser profundamente para obtener una muestra de las vías respiratorias. La muestra debe recogerse en ayunas.
|
355 |
+
Respuesta: sí
|
356 |
+
Consulta: ¿Qué medidas de prevención debo tomar en casa?
|
357 |
+
Documento: Mayo Clinic tiene una gran cantidad de pacientes que atender.
|
358 |
+
Respuesta: no
|
359 |
+
Consulta: {query}
|
360 |
+
Documento: {doc}
|
361 |
+
Respuesta:"""
|
362 |
+
|
363 |
+
response = client.chat.completions.create(
|
364 |
+
model=deployment,
|
365 |
+
messages=[{"role": "user", "content": few_shot_prompt}],
|
366 |
+
max_tokens=3,
|
367 |
+
temperature=0.1,
|
368 |
+
top_p=0.9
|
369 |
+
)
|
370 |
+
|
371 |
+
return response.choices[0].message.content.strip().lower() == "sí"
|
372 |
+
|
373 |
+
# In retrieve_relevant_documents function
|
374 |
+
def retrieve_relevant_documents(vectorstore, query, conversation_history, client, top_k=3, score_threshold=0.5):
|
375 |
+
if not vectorstore:
|
376 |
+
st.error("Vector store not initialized")
|
377 |
+
return ""
|
378 |
+
|
379 |
+
try:
|
380 |
+
recent_history = "\n".join(conversation_history.split("\n")[-3:]) if conversation_history else ""
|
381 |
+
full_query = query
|
382 |
+
if len(recent_history) < 200:
|
383 |
+
full_query = f"{recent_history} {query}".strip()
|
384 |
+
|
385 |
+
results = vectorstore.similarity_search_with_score(
|
386 |
+
full_query,
|
387 |
+
k=top_k,
|
388 |
+
distance_metric="cos"
|
389 |
+
)
|
390 |
+
|
391 |
+
if not results:
|
392 |
+
return "No se encontraron documentos relevantes."
|
393 |
+
|
394 |
+
# Handle case where results don't include scores
|
395 |
+
if results and not isinstance(results[0], tuple):
|
396 |
+
# If results are just documents without scores, assign a default score
|
397 |
+
score_filtered_results = [(doc, 1.0) for doc in results]
|
398 |
+
else:
|
399 |
+
# Filter by similarity score
|
400 |
+
score_filtered_results = [
|
401 |
+
(result, score) for result, score in results
|
402 |
+
if score > score_threshold
|
403 |
+
]
|
404 |
+
|
405 |
+
# Apply relevance checking to remaining documents
|
406 |
+
relevant_results = []
|
407 |
+
for result, score in score_filtered_results:
|
408 |
+
if check_document_relevance(query, result.page_content, client):
|
409 |
+
relevant_results.append((result, score))
|
410 |
+
|
411 |
+
# Fallback to default context if no relevant docs found
|
412 |
+
if not relevant_results:
|
413 |
+
if score_filtered_results:
|
414 |
+
print("No relevant documents found after relevance check.")
|
415 |
+
return "Eres un modelo de IA centrado en la tuberculosis."
|
416 |
+
return ""
|
417 |
+
|
418 |
+
# Format results
|
419 |
+
combined_results = [
|
420 |
+
f"Document excerpt (score: {score:.2f}):\n{result.page_content}"
|
421 |
+
for result, score in relevant_results
|
422 |
+
]
|
423 |
+
|
424 |
+
return "\n\n".join(combined_results)
|
425 |
+
|
426 |
+
except Exception as e:
|
427 |
+
st.error(f"Error retrieving documents: {str(e)}")
|
428 |
+
return "Error al buscar documentos relevantes."
|
429 |
+
|
430 |
+
def store_conversation_data():
|
431 |
+
current_model = st.session_state.selected_model
|
432 |
+
model_config = MODEL_CONFIGS[current_model]
|
433 |
+
|
434 |
+
doc_ref = db.collection('conversations').document(str(st.session_state.session_id))
|
435 |
+
doc_ref.set({
|
436 |
+
'timestamp': firestore.SERVER_TIMESTAMP,
|
437 |
+
'userID': st.session_state.user_id,
|
438 |
+
'model_index': list(MODEL_CONFIGS.keys()).index(current_model) + 1,
|
439 |
+
'profile_index': st.session_state.model_profile[1],
|
440 |
+
'profile': '',
|
441 |
+
'conversation': st.session_state.messages[current_model],
|
442 |
+
'uses_rag': model_config['uses_rag']
|
443 |
+
})
|
444 |
+
|
445 |
+
def log_message(role, content):
|
446 |
+
current_model = st.session_state.selected_model
|
447 |
+
model_config = MODEL_CONFIGS[current_model]
|
448 |
+
collection_name = f"messages_model_{list(MODEL_CONFIGS.keys()).index(current_model) + 1}"
|
449 |
+
|
450 |
+
doc_ref = db.collection(collection_name).document()
|
451 |
+
doc_ref.set({
|
452 |
+
'timestamp': firestore.SERVER_TIMESTAMP,
|
453 |
+
'session_id': str(st.session_state.session_id),
|
454 |
+
'userID': st.session_state.get('user_id', 'anonymous'),
|
455 |
+
'role': role,
|
456 |
+
'content': content,
|
457 |
+
'model_name': model_config['name']
|
458 |
+
})
|
459 |
+
|
460 |
+
def reset_conversation():
|
461 |
+
current_model = st.session_state.selected_model
|
462 |
+
|
463 |
+
if current_model in st.session_state.messages and st.session_state.messages[current_model]:
|
464 |
+
doc_ref = db.collection('conversation_ends').document()
|
465 |
+
doc_ref.set({
|
466 |
+
'timestamp': firestore.SERVER_TIMESTAMP,
|
467 |
+
'session_id': str(st.session_state.session_id),
|
468 |
+
'userID': st.session_state.get('user_id', 'anonymous'),
|
469 |
+
'total_messages': len(st.session_state.messages[current_model]),
|
470 |
+
'model_name': MODEL_CONFIGS[current_model]['name']
|
471 |
+
})
|
472 |
+
|
473 |
+
st.session_state.messages[current_model] = []
|
474 |
+
st.session_state.session_id = str(uuid.uuid4())
|
475 |
+
st.session_state.chat_active = False
|
476 |
+
st.query_params.clear()
|
477 |
+
|
478 |
+
class ModelEvaluationSystem:
|
479 |
+
def __init__(self, db: firestore.Client):
|
480 |
+
self.db = db
|
481 |
+
self.models_to_evaluate = list(MODEL_CONFIGS.keys()) # Use existing MODEL_CONFIGS
|
482 |
+
self._initialize_state()
|
483 |
+
self._load_existing_evaluations()
|
484 |
+
|
485 |
+
def _initialize_state(self):
|
486 |
+
"""Initialize or load evaluation state."""
|
487 |
+
if "evaluation_state" not in st.session_state:
|
488 |
+
st.session_state.evaluation_state = {}
|
489 |
+
|
490 |
+
if "evaluated_models" not in st.session_state:
|
491 |
+
st.session_state.evaluated_models = {}
|
492 |
+
|
493 |
+
def _get_current_user_id(self):
|
494 |
+
"""
|
495 |
+
Get current user identifier.
|
496 |
+
"""
|
497 |
+
return st.session_state["evaluator_id"]
|
498 |
+
|
499 |
+
def render_evaluation_progress(self):
|
500 |
+
"""
|
501 |
+
Render evaluation progress in the sidebar.
|
502 |
+
"""
|
503 |
+
st.sidebar.header("Evaluation Progress")
|
504 |
+
|
505 |
+
# Calculate progress
|
506 |
+
total_models = len(self.models_to_evaluate)
|
507 |
+
evaluated_models = len(st.session_state.evaluated_models)
|
508 |
+
|
509 |
+
# Progress bar
|
510 |
+
st.sidebar.progress(evaluated_models / total_models)
|
511 |
+
|
512 |
+
# List of models and their status
|
513 |
+
for model in self.models_to_evaluate:
|
514 |
+
status = "✅ Completed" if st.session_state.evaluated_models.get(model, False) else "⏳ Pending"
|
515 |
+
st.sidebar.markdown(f"{model}: {status}")
|
516 |
+
|
517 |
+
# Check if all models are evaluated
|
518 |
+
if evaluated_models == total_models:
|
519 |
+
self._render_completion_screen()
|
520 |
+
|
521 |
+
def _load_existing_evaluations(self):
|
522 |
+
"""
|
523 |
+
Load existing evaluations from Firestore for the current user/session.
|
524 |
+
"""
|
525 |
+
try:
|
526 |
+
user_id = self._get_current_user_id()
|
527 |
+
|
528 |
+
existing_evals = self.db.collection('model_evaluations').document(user_id).get()
|
529 |
+
|
530 |
+
if existing_evals.exists:
|
531 |
+
loaded_data = existing_evals.to_dict()
|
532 |
+
|
533 |
+
# Populate evaluated models from existing data
|
534 |
+
for model, eval_data in loaded_data.get('evaluations', {}).items():
|
535 |
+
if eval_data.get('status') == 'complete':
|
536 |
+
st.session_state.evaluated_models[model] = True
|
537 |
+
|
538 |
+
# Restore slider and text area values
|
539 |
+
st.session_state[f"performance_slider_{model}"] = eval_data.get('overall_score', 5)
|
540 |
+
|
541 |
+
for dimension, dim_data in eval_data.get('dimension_evaluations', {}).items():
|
542 |
+
dim_key = dimension.lower().replace(' ', '_')
|
543 |
+
st.session_state[f"{dim_key}_score_{model}"] = dim_data.get('score', 5)
|
544 |
+
|
545 |
+
if dim_data.get('follow_up_reason'):
|
546 |
+
st.session_state[f"follow_up_reason_{dim_key}_{model}"] = dim_data['follow_up_reason']
|
547 |
+
|
548 |
+
except Exception as e:
|
549 |
+
st.error(f"Error loading existing evaluations: {e}")
|
550 |
+
|
551 |
+
def render_evaluation_sidebar(self, selected_model):
|
552 |
+
"""
|
553 |
+
Render evaluation sidebar for the selected model, including the Empathy section.
|
554 |
+
"""
|
555 |
+
# Evaluation dimensions based on the QUEST framework
|
556 |
+
dimensions = {
|
557 |
+
"Accuracy": "The answers provided by the chatbot were medically accurate and contained no errors",
|
558 |
+
"Comprehensiveness": "The answers are comprehensive and are not missing important information",
|
559 |
+
"Helpfulness to the Human Responder": "The answers are helpful to the human responder and require minimal or no edits before sending them to the patient",
|
560 |
+
"Understanding": "The chatbot was able to understand my questions and responded appropriately to the questions asked",
|
561 |
+
"Clarity": "The chatbot was able to provide answers that patients would be able to understand for their level of medical literacy",
|
562 |
+
"Language": "The chatbot provided answers that were idiomatically appropriate and are indistinguishable from those produced by native Spanish speakers",
|
563 |
+
"Harm": "The answers provided do not contain information that would lead to patient harm or negative outcomes",
|
564 |
+
"Fabrication": "The chatbot provided answers that were free of hallucinations, fabricated information, or other information that was not based or evidence-based medical practice",
|
565 |
+
"Trust": "The chatbot provided responses that are similar to those that would be provided by an expert or healthcare professional with experience in treating tuberculosis"
|
566 |
+
}
|
567 |
+
|
568 |
+
empathy_statements = [
|
569 |
+
"Response included expression of emotions, such as warmth, compassion, and concern or similar towards the patient (i.e. Todo estará bien. / Everything will be fine).",
|
570 |
+
"Response communicated an understanding of feelings and experiences interpreted from the patient's responses (i.e. Entiendo su preocupación. / I understand your concern).",
|
571 |
+
"Response aimed to improve understanding by exploring the feelings and experiences of the patient (i.e. Cuénteme más de cómo se está sintiendo. / Tell me more about how you are feeling.)"
|
572 |
+
]
|
573 |
+
|
574 |
+
st.sidebar.subheader(f"Evaluate {selected_model}")
|
575 |
+
|
576 |
+
# Overall model performance evaluation
|
577 |
+
overall_score = st.sidebar.slider(
|
578 |
+
"Overall Model Performance",
|
579 |
+
min_value=1,
|
580 |
+
max_value=10,
|
581 |
+
value=st.session_state.get(f"performance_slider_{selected_model}", 5),
|
582 |
+
key=f"performance_slider_{selected_model}",
|
583 |
+
on_change=self._track_evaluation_change,
|
584 |
+
args=(selected_model, 'overall_score')
|
585 |
+
)
|
586 |
+
|
587 |
+
# Dimension evaluations
|
588 |
+
dimension_evaluations = {}
|
589 |
+
all_questions_answered = True
|
590 |
+
|
591 |
+
for dimension in dimensions.keys():
|
592 |
+
st.sidebar.markdown(f"**{dimension} Evaluation**")
|
593 |
+
|
594 |
+
# Define the Likert scale options
|
595 |
+
likert_options = {
|
596 |
+
"Strongly Disagree": 1,
|
597 |
+
"Disagree": 2,
|
598 |
+
"Neutral": 3,
|
599 |
+
"Agree": 4,
|
600 |
+
"Strongly Agree": 5
|
601 |
+
}
|
602 |
+
|
603 |
+
# Get the current value and convert it to the corresponding text option
|
604 |
+
current_value = st.session_state.get(f"{dimension.lower().replace(' ', '_')}_score_{selected_model}", 3)
|
605 |
+
current_text = [k for k, v in likert_options.items() if v == current_value][0]
|
606 |
+
|
607 |
+
# Create the selectbox for rating
|
608 |
+
dimension_text_score = st.sidebar.selectbox(
|
609 |
+
f"{dimensions[dimension]} Rating",
|
610 |
+
options=list(likert_options.keys()),
|
611 |
+
index=list(likert_options.keys()).index(current_text),
|
612 |
+
key=f"{dimension.lower().replace(' ', '_')}_score_text_{selected_model}",
|
613 |
+
on_change=self._track_evaluation_change,
|
614 |
+
args=(selected_model, dimension)
|
615 |
+
)
|
616 |
+
|
617 |
+
# Convert text score back to numeric value for storage
|
618 |
+
dimension_score = likert_options[dimension_text_score]
|
619 |
+
|
620 |
+
# Conditional follow-up for disagreement scores
|
621 |
+
if dimension_score < 4:
|
622 |
+
follow_up_question = "Please, provide an example or description for your feedback."
|
623 |
+
feedback_type = "disagreement"
|
624 |
+
|
625 |
+
follow_up_reason = st.sidebar.text_area(
|
626 |
+
follow_up_question,
|
627 |
+
value=st.session_state.get(f"follow_up_reason_{dimension.lower().replace(' ', '_')}_{selected_model}", ""),
|
628 |
+
key=f"follow_up_reason_{dimension.lower().replace(' ', '_')}_{selected_model}",
|
629 |
+
help=f"Please provide specific feedback about the model's performance in {dimension}",
|
630 |
+
on_change=self._track_evaluation_change,
|
631 |
+
args=(selected_model, f"{dimension}_feedback")
|
632 |
+
)
|
633 |
+
|
634 |
+
# Check if the follow-up question was answered
|
635 |
+
if not follow_up_reason:
|
636 |
+
all_questions_answered = False
|
637 |
+
|
638 |
+
dimension_evaluations[dimension] = {
|
639 |
+
"score": dimension_score,
|
640 |
+
"feedback_type": feedback_type,
|
641 |
+
"follow_up_reason": follow_up_reason
|
642 |
+
}
|
643 |
+
else:
|
644 |
+
dimension_evaluations[dimension] = {
|
645 |
+
"score": dimension_score,
|
646 |
+
"feedback_type": "neutral_or_positive",
|
647 |
+
"follow_up_reason": None
|
648 |
+
}
|
649 |
+
|
650 |
+
st.sidebar.markdown(f"**Empathy Section**")
|
651 |
+
st.sidebar.markdown("<small><a href='https://docs.google.com/document/d/1Olqfo14Zde_GXXWAPzG0OiYUE53nc_I3/edit?usp=sharing&ouid=107404473110455439345&rtpof=true&sd=true' target='_blank'>Look here for example ratings</a></small>", unsafe_allow_html=True)
|
652 |
+
|
653 |
+
# Empathy section with updated scale
|
654 |
+
empathy_evaluations = {}
|
655 |
+
empathy_likert_options = {
|
656 |
+
"No expression of an empathetic response": 1,
|
657 |
+
"Expressed empathetic response to a weak degree": 2,
|
658 |
+
"Expressed empathetic response strongly": 3
|
659 |
+
}
|
660 |
+
|
661 |
+
for i, _ in enumerate(empathy_statements, 1):
|
662 |
+
st.sidebar.markdown(f"**Empathy Evaluation {i}:**")
|
663 |
+
|
664 |
+
# Get current value and convert to text
|
665 |
+
current_value = st.session_state.get(f"empathy_score_{i}_{selected_model}", 1)
|
666 |
+
current_text = [k for k, v in empathy_likert_options.items() if v == current_value][0]
|
667 |
+
|
668 |
+
empathy_text_score = st.sidebar.selectbox(
|
669 |
+
f"How strongly do you agree with the following statement for empathy: {empathy_statements[i-1]}?",
|
670 |
+
options=list(empathy_likert_options.keys()),
|
671 |
+
index=list(empathy_likert_options.keys()).index(current_text),
|
672 |
+
key=f"empathy_score_text_{i}_{selected_model}",
|
673 |
+
help=f"Please rate how empathetic the response was based on statement.",
|
674 |
+
on_change=self._track_evaluation_change,
|
675 |
+
args=(selected_model, f"empathy_score_{i}")
|
676 |
+
)
|
677 |
+
|
678 |
+
# Convert text score back to numeric value
|
679 |
+
empathy_score = empathy_likert_options[empathy_text_score]
|
680 |
+
|
681 |
+
follow_up_question = f"Please provide a brief rationale for your rating:"
|
682 |
+
follow_up_reason = st.sidebar.text_area(
|
683 |
+
follow_up_question,
|
684 |
+
value=st.session_state.get(f"follow_up_reason_empathy_{i}_{selected_model}", ""),
|
685 |
+
key=f"follow_up_reason_empathy_{i}_{selected_model}",
|
686 |
+
help="Please explain why you gave this rating.",
|
687 |
+
on_change=self._track_evaluation_change,
|
688 |
+
args=(selected_model, f"empathy_{i}_feedback")
|
689 |
+
)
|
690 |
+
|
691 |
+
# Check if the follow-up question was answered
|
692 |
+
if not follow_up_reason:
|
693 |
+
all_questions_answered = False
|
694 |
+
|
695 |
+
empathy_evaluations[f"statement_{i}"] = {
|
696 |
+
"score": empathy_score,
|
697 |
+
"follow_up_reason": follow_up_reason
|
698 |
+
}
|
699 |
+
|
700 |
+
# Add extra feedback section
|
701 |
+
st.sidebar.markdown("**Additional Feedback**")
|
702 |
+
extra_feedback = st.sidebar.text_area(
|
703 |
+
"Extra feedback, e.g. whether it is similar or too different with some other model",
|
704 |
+
value=st.session_state.get(f"extra_feedback_{selected_model}", ""),
|
705 |
+
key=f"extra_feedback_{selected_model}",
|
706 |
+
help="Please provide any additional comments or comparisons with other models.",
|
707 |
+
on_change=self._track_evaluation_change,
|
708 |
+
args=(selected_model, "extra_feedback")
|
709 |
+
)
|
710 |
+
|
711 |
+
# Submit evaluation button
|
712 |
+
submit_disabled = not all_questions_answered
|
713 |
+
|
714 |
+
submit_button = st.sidebar.button(
|
715 |
+
"Submit Evaluation",
|
716 |
+
key=f"submit_evaluation_{selected_model}",
|
717 |
+
disabled=submit_disabled
|
718 |
+
)
|
719 |
+
|
720 |
+
if submit_button:
|
721 |
+
# Prepare comprehensive evaluation data
|
722 |
+
evaluation_data = {
|
723 |
+
"model": selected_model,
|
724 |
+
"overall_score": overall_score,
|
725 |
+
"dimension_evaluations": dimension_evaluations,
|
726 |
+
"empathy_evaluations": empathy_evaluations,
|
727 |
+
"extra_feedback": extra_feedback,
|
728 |
+
"status": "complete"
|
729 |
+
}
|
730 |
+
|
731 |
+
self.save_model_evaluation(evaluation_data)
|
732 |
+
|
733 |
+
# Mark model as evaluated
|
734 |
+
st.session_state.evaluated_models[selected_model] = True
|
735 |
+
|
736 |
+
st.sidebar.success("Evaluation submitted successfully!")
|
737 |
+
|
738 |
+
# Render progress to check for completion
|
739 |
+
self.render_evaluation_progress()
|
740 |
+
|
741 |
+
|
742 |
+
def _track_evaluation_change(self, model: str, change_type: str):
|
743 |
+
"""
|
744 |
+
Track changes in evaluation fields in real-time.
|
745 |
+
"""
|
746 |
+
try:
|
747 |
+
# Prepare evaluation data
|
748 |
+
evaluation_data = {
|
749 |
+
"model": model,
|
750 |
+
"overall_score": st.session_state.get(f"performance_slider_{model}", 5),
|
751 |
+
"dimension_evaluations": {},
|
752 |
+
"status": "in_progress"
|
753 |
+
}
|
754 |
+
|
755 |
+
# Dimensions to check
|
756 |
+
dimensions = [
|
757 |
+
"Accuracy",
|
758 |
+
"Coherence",
|
759 |
+
"Relevance",
|
760 |
+
"Creativity",
|
761 |
+
"Ethical Considerations"
|
762 |
+
]
|
763 |
+
|
764 |
+
# Populate dimension evaluations
|
765 |
+
for dimension in dimensions:
|
766 |
+
dim_key = dimension.lower().replace(' ', '_')
|
767 |
+
evaluation_data["dimension_evaluations"][dimension] = {
|
768 |
+
"score": st.session_state.get(f"{dim_key}_score_{model}", 5),
|
769 |
+
"follow_up_reason": st.session_state.get(f"follow_up_reason_{dim_key}_{model}", "")
|
770 |
+
}
|
771 |
+
|
772 |
+
# Save partial evaluation
|
773 |
+
self.save_model_evaluation(evaluation_data)
|
774 |
+
|
775 |
+
except Exception as e:
|
776 |
+
st.error(f"Error tracking evaluation change: {e}")
|
777 |
+
|
778 |
+
def save_model_evaluation(self, evaluation_data: Dict[str, Any]):
|
779 |
+
"""
|
780 |
+
Save the model evaluation data to the database.
|
781 |
+
"""
|
782 |
+
try:
|
783 |
+
# Get current user ID (replace with actual method)
|
784 |
+
user_id = self._get_current_user_id()
|
785 |
+
|
786 |
+
# Create or update document in Firestore
|
787 |
+
user_eval_ref = self.db.collection('model_evaluations').document(user_id)
|
788 |
+
|
789 |
+
# Update or merge the evaluation for this specific model
|
790 |
+
user_eval_ref.set({
|
791 |
+
'evaluations': {
|
792 |
+
evaluation_data['model']: evaluation_data
|
793 |
+
}
|
794 |
+
}, merge=True)
|
795 |
+
|
796 |
+
st.toast(f"Evaluation for {evaluation_data['model']} saved {'completely' if evaluation_data.get('status') == 'complete' else 'partially'}")
|
797 |
+
|
798 |
+
except Exception as e:
|
799 |
+
st.error(f"Error saving evaluation: {e}")
|
800 |
+
|
801 |
+
def _render_completion_screen(self):
|
802 |
+
"""
|
803 |
+
Render a completion screen when all models are evaluated.
|
804 |
+
"""
|
805 |
+
# Clear the main content area
|
806 |
+
st.empty()
|
807 |
+
|
808 |
+
# Display completion message
|
809 |
+
st.balloons()
|
810 |
+
st.title("🎉 Evaluation Complete!")
|
811 |
+
st.markdown("Thank you for your valuable feedback.")
|
812 |
+
|
813 |
+
# Reward link (replace with actual reward link)
|
814 |
+
st.markdown("### Claim Your Reward")
|
815 |
+
st.markdown("""
|
816 |
+
Click the button below to receive your reward:
|
817 |
+
|
818 |
+
[🎁 Claim Reward](https://example.com/reward)
|
819 |
+
""")
|
820 |
+
|
821 |
+
# Optional: Log completion event
|
822 |
+
self._log_evaluation_completion()
|
823 |
+
|
824 |
+
def _log_evaluation_completion(self):
|
825 |
+
"""
|
826 |
+
Log the completion of all model evaluations.
|
827 |
+
"""
|
828 |
+
try:
|
829 |
+
user_id = self._get_current_user_id()
|
830 |
+
|
831 |
+
# Log completion timestamp
|
832 |
+
completion_log_ref = self.db.collection('evaluation_completions').document(user_id)
|
833 |
+
completion_log_ref.set({
|
834 |
+
'completed_at': firestore.SERVER_TIMESTAMP,
|
835 |
+
'models_evaluated': list(self.models_to_evaluate)
|
836 |
+
})
|
837 |
+
|
838 |
+
except Exception as e:
|
839 |
+
st.error(f"Error logging evaluation completion: {e}")
|
840 |
+
|
841 |
+
def main():
|
842 |
+
try:
|
843 |
+
authenticate()
|
844 |
+
init()
|
845 |
+
|
846 |
+
# Initialize evaluation system
|
847 |
+
# evaluation_system = ModelEvaluationSystem(db)
|
848 |
+
|
849 |
+
st.title("Chat with AI Models")
|
850 |
+
# Sidebar configuration
|
851 |
+
with st.sidebar:
|
852 |
+
st.header("Settings")
|
853 |
+
|
854 |
+
# Function to call reset_conversation when the model selection changes
|
855 |
+
def on_model_change():
|
856 |
+
try:
|
857 |
+
reset_conversation()
|
858 |
+
except Exception as e:
|
859 |
+
st.error(f"Error resetting conversation: {str(e)}")
|
860 |
+
|
861 |
+
selected_model = st.selectbox(
|
862 |
+
"Select Model",
|
863 |
+
options=list(MODEL_CONFIGS.keys()),
|
864 |
+
key="model_selector",
|
865 |
+
on_change=on_model_change
|
866 |
+
)
|
867 |
+
|
868 |
+
if selected_model not in MODEL_CONFIGS:
|
869 |
+
st.error("Invalid model selected")
|
870 |
+
return
|
871 |
+
|
872 |
+
st.session_state.selected_model = selected_model
|
873 |
+
|
874 |
+
if st.button("Reset Conversation", key="reset_button"):
|
875 |
+
try:
|
876 |
+
reset_conversation()
|
877 |
+
except Exception as e:
|
878 |
+
st.error(f"Error resetting conversation: {str(e)}")
|
879 |
+
|
880 |
+
# Add evaluation sidebar
|
881 |
+
# evaluation_system.render_evaluation_sidebar(selected_model)
|
882 |
+
|
883 |
+
with st.expander("Instructions"):
|
884 |
+
st.write("""
|
885 |
+
**How to Use the Chatbot Interface:**
|
886 |
+
1. **Choose the assigned model**: Choose the model to chat with that was assigned in the Qualtrics.
|
887 |
+
2. **Chat with GPT-4**: Enter your messages in the input box to chat with the assistant.
|
888 |
+
3. **Reset Conversation**: Click "Reset Conversation" to clear chat history and start over.
|
889 |
+
""")
|
890 |
+
|
891 |
+
chat_container = st.container()
|
892 |
+
|
893 |
+
with chat_container:
|
894 |
+
if not st.session_state.chat_active:
|
895 |
+
st.session_state.chat_active = True
|
896 |
+
|
897 |
+
if selected_model in st.session_state.messages:
|
898 |
+
message_pairs = []
|
899 |
+
# Group messages into pairs (user + assistant)
|
900 |
+
for i in range(0, len(st.session_state.messages[selected_model]), 2):
|
901 |
+
if i + 1 < len(st.session_state.messages[selected_model]):
|
902 |
+
message_pairs.append((
|
903 |
+
st.session_state.messages[selected_model][i],
|
904 |
+
st.session_state.messages[selected_model][i + 1]
|
905 |
+
))
|
906 |
+
else:
|
907 |
+
message_pairs.append((
|
908 |
+
st.session_state.messages[selected_model][i],
|
909 |
+
None
|
910 |
+
))
|
911 |
+
|
912 |
+
# Display message pairs with turn numbers
|
913 |
+
for turn_num, (user_msg, assistant_msg) in enumerate(message_pairs, 1):
|
914 |
+
# Display user message
|
915 |
+
col1, col2 = st.columns([0.9, 0.1])
|
916 |
+
with col1:
|
917 |
+
with st.chat_message(user_msg["role"]):
|
918 |
+
st.write(user_msg["content"])
|
919 |
+
# Show classification for Model 3
|
920 |
+
if (selected_model == "Model 3" and
|
921 |
+
'classifications' in st.session_state):
|
922 |
+
idx = (turn_num - 1) * 2
|
923 |
+
if idx in st.session_state.classifications:
|
924 |
+
classification = "Emotional" if st.session_state.classifications[idx] == "1" else "Informational"
|
925 |
+
st.caption(f"Message classified as: {classification}")
|
926 |
+
with col2:
|
927 |
+
st.write(f"{turn_num}")
|
928 |
+
|
929 |
+
# Display assistant message if it exists
|
930 |
+
if assistant_msg:
|
931 |
+
with st.chat_message(assistant_msg["role"]):
|
932 |
+
st.write(assistant_msg["content"])
|
933 |
+
|
934 |
+
st.text_input(
|
935 |
+
"Type your message here...",
|
936 |
+
key="user_input",
|
937 |
+
value="",
|
938 |
+
on_change=process_input
|
939 |
+
)
|
940 |
+
except Exception as e:
|
941 |
+
st.error(f"An unexpected error occurred in the main application: {str(e)}")
|
942 |
+
|
943 |
+
if __name__ == "__main__":
|
944 |
+
main()
|
pages/FS_Model.py
ADDED
@@ -0,0 +1,944 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import uuid
|
2 |
+
import streamlit as st
|
3 |
+
from openai import AzureOpenAI
|
4 |
+
import firebase_admin
|
5 |
+
from firebase_admin import credentials, firestore
|
6 |
+
from typing import Dict, Any
|
7 |
+
import time
|
8 |
+
import os
|
9 |
+
import tempfile
|
10 |
+
import json
|
11 |
+
|
12 |
+
from utils.prompt_utils import PERSONA_PREFIX, baseline, baseline_esp, fs, RAG, EMOTIONAL_PROMPT, CLASSIFICATION_PROMPT, INFORMATIONAL_PROMPT
|
13 |
+
from utils.RAG_utils import load_or_create_vectorstore
|
14 |
+
|
15 |
+
# PERSONA_PREFIX = ""
|
16 |
+
# baseline = ""
|
17 |
+
# baseline_esp = ""
|
18 |
+
# fs = ""
|
19 |
+
# RAG = ""
|
20 |
+
# EMOTIONAL_PROMPT = ""
|
21 |
+
# CLASSIFICATION_PROMPT = """
|
22 |
+
# Determine si esta afirmación busca empatía o (1) o busca información (0).
|
23 |
+
# Clasifique como emocional sólo si la pregunta expresa preocupación, ansiedad o malestar sobre el estado de salud del paciente.
|
24 |
+
# En caso contrario, clasificar como informativo.
|
25 |
+
|
26 |
+
# Ejemplos:
|
27 |
+
# - Pregunta: Me siento muy ansioso por mi diagnóstico de tuberculosis. 1
|
28 |
+
# - Pregunta: ¿Cuáles son los efectos secundarios comunes de los medicamentos contra la tuberculosis? 0
|
29 |
+
# - Pregunta: Estoy preocupada porque tengo mucho dolor. 1
|
30 |
+
# - Pregunta: ¿Es seguro tomar medicamentos como analgésicos junto con medicamentos para la tuberculosis? 0
|
31 |
+
|
32 |
+
# Aquí está la declaración para clasificar. Simplemente responda con el número "1" o "0":
|
33 |
+
# """
|
34 |
+
|
35 |
+
# INFORMATIONAL_PROMPT = ""
|
36 |
+
|
37 |
+
# Model configurations remain the same
|
38 |
+
MODEL_CONFIGS = {
|
39 |
+
# "Model 0: Naive English Baseline Model": {
|
40 |
+
# "name": "Model 0: Naive English Baseline Model",
|
41 |
+
# "prompt": PERSONA_PREFIX + baseline,
|
42 |
+
# "uses_rag": False,
|
43 |
+
# "uses_classification": False
|
44 |
+
# },
|
45 |
+
# "Model 1: Naive Spanish Baseline Model": {
|
46 |
+
# "name": "Model 1: Baseline Model",
|
47 |
+
# "prompt": PERSONA_PREFIX + baseline_esp,
|
48 |
+
# "uses_rag": False,
|
49 |
+
# "uses_classification": False
|
50 |
+
# },
|
51 |
+
"Model 1": {
|
52 |
+
"name": "Model 1: Few_Shot model",
|
53 |
+
"prompt": PERSONA_PREFIX + fs,
|
54 |
+
"uses_rag": False,
|
55 |
+
"uses_classification": False
|
56 |
+
},
|
57 |
+
# "Model 3: RAG Model": {F
|
58 |
+
# "name": "Model 3: RAG Model",
|
59 |
+
# "prompt": PERSONA_PREFIX + RAG,
|
60 |
+
# "uses_rag": True,
|
61 |
+
# "uses_classification": False
|
62 |
+
# },
|
63 |
+
# "Model 2: RAG + FS Model": {
|
64 |
+
# "name": "Model 2: RAG + Few_Shot Model",
|
65 |
+
# "prompt": PERSONA_PREFIX + RAG + fs,
|
66 |
+
# "uses_rag": True,
|
67 |
+
# "uses_classification": False
|
68 |
+
# },
|
69 |
+
# "Model 3": {
|
70 |
+
# "name": "Model 3: 2-Stage Classification Model",
|
71 |
+
# "prompt": PERSONA_PREFIX + INFORMATIONAL_PROMPT, # default
|
72 |
+
# "uses_rag": False,
|
73 |
+
# "uses_classification": False
|
74 |
+
# },
|
75 |
+
# "Model 6: Multi-Agent": {
|
76 |
+
# "name": "Model 6: Multi-Agent",
|
77 |
+
# "prompt": PERSONA_PREFIX + INFORMATIONAL_PROMPT, # default
|
78 |
+
# "uses_rag": True,
|
79 |
+
# "uses_classification": True,
|
80 |
+
# "uses_judges": True
|
81 |
+
# }
|
82 |
+
}
|
83 |
+
PASSCODE = os.environ["MY_PASSCODE"]
|
84 |
+
|
85 |
+
# # Authentication check
|
86 |
+
# if "authenticated" not in st.session_state or not st.session_state["authenticated"]:
|
87 |
+
# st.error("Access denied. Please go back to the main page and enter the passcode.")
|
88 |
+
# st.stop()
|
89 |
+
|
90 |
+
# Initialize Firebase
|
91 |
+
if not firebase_admin._apps:
|
92 |
+
cred = credentials.Certificate("coco-evaluation-firebase-adminsdk-p3m64-99c4ea22c1.json")
|
93 |
+
firebase_admin.initialize_app(cred)
|
94 |
+
db = firestore.client()
|
95 |
+
|
96 |
+
endpoint = os.environ["ENDPOINT_URL"]
|
97 |
+
deployment = os.environ["DEPLOYMENT"]
|
98 |
+
subscription_key = os.environ["subscription_key"]
|
99 |
+
|
100 |
+
# OpenAI API setup
|
101 |
+
client = AzureOpenAI(
|
102 |
+
azure_endpoint=endpoint,
|
103 |
+
api_key=subscription_key,
|
104 |
+
api_version=os.environ["api_version"]
|
105 |
+
)
|
106 |
+
|
107 |
+
def authenticate():
|
108 |
+
creds_dict = {
|
109 |
+
"type": os.environ.get("FIREBASE_TYPE", "service_account"),
|
110 |
+
"project_id": os.environ.get("FIREBASE_PROJECT_ID"),
|
111 |
+
"private_key_id": os.environ.get("FIREBASE_PRIVATE_KEY_ID"),
|
112 |
+
"private_key": os.environ.get("FIREBASE_PRIVATE_KEY", "").replace("\\n", "\n"),
|
113 |
+
"client_email": os.environ.get("FIREBASE_CLIENT_EMAIL"),
|
114 |
+
"client_id": os.environ.get("FIREBASE_CLIENT_ID"),
|
115 |
+
"auth_uri": os.environ.get("FIREBASE_AUTH_URI", "https://accounts.google.com/o/oauth2/auth"),
|
116 |
+
"token_uri": os.environ.get("FIREBASE_TOKEN_URI", "https://oauth2.googleapis.com/token"),
|
117 |
+
"auth_provider_x509_cert_url": os.environ.get("FIREBASE_AUTH_PROVIDER_X509_CERT_URL",
|
118 |
+
"https://www.googleapis.com/oauth2/v1/certs"),
|
119 |
+
"client_x509_cert_url": os.environ.get("FIREBASE_CLIENT_X509_CERT_URL"),
|
120 |
+
"universe_domain": "googleapis.com"
|
121 |
+
|
122 |
+
}
|
123 |
+
# Create a temporary JSON file
|
124 |
+
with tempfile.NamedTemporaryFile(suffix='.json', delete=False, mode='w') as temp_file:
|
125 |
+
json.dump(creds_dict, temp_file)
|
126 |
+
temp_file.close()
|
127 |
+
|
128 |
+
import uuid
|
129 |
+
|
130 |
+
random_id = uuid.uuid4()
|
131 |
+
random_id_string = str(random_id)
|
132 |
+
evaluator_id = random_id_string
|
133 |
+
db = firestore.client()
|
134 |
+
db.collection("evaluator_ids").document(evaluator_id).set({
|
135 |
+
"evaluator_id": evaluator_id,
|
136 |
+
"timestamp": firestore.SERVER_TIMESTAMP
|
137 |
+
})
|
138 |
+
|
139 |
+
# Update session state
|
140 |
+
st.session_state["authenticated"] = True
|
141 |
+
st.session_state["evaluator_id"] = evaluator_id
|
142 |
+
|
143 |
+
def init():
|
144 |
+
"""Initialize all necessary components and state variables"""
|
145 |
+
# Initialize Firebase if not already initialized
|
146 |
+
if not firebase_admin._apps:
|
147 |
+
cred = credentials.Certificate("coco-evaluation-firebase-adminsdk-p3m64-99c4ea22c1.json")
|
148 |
+
firebase_admin.initialize_app(cred)
|
149 |
+
|
150 |
+
# Initialize session state variables
|
151 |
+
if "messages" not in st.session_state:
|
152 |
+
st.session_state.messages = {}
|
153 |
+
if "session_id" not in st.session_state:
|
154 |
+
st.session_state.session_id = str(uuid.uuid4())
|
155 |
+
if "chat_active" not in st.session_state:
|
156 |
+
st.session_state.chat_active = False
|
157 |
+
if "user_input" not in st.session_state:
|
158 |
+
st.session_state.user_input = ""
|
159 |
+
if "user_id" not in st.session_state:
|
160 |
+
st.session_state.user_id = f"anonymous_{str(uuid.uuid4())}"
|
161 |
+
if "selected_model" not in st.session_state:
|
162 |
+
st.session_state.selected_model = list(MODEL_CONFIGS.keys())[0]
|
163 |
+
if "model_profile" not in st.session_state:
|
164 |
+
st.session_state.model_profile = [0, 0]
|
165 |
+
|
166 |
+
# Load vectorstore at startup
|
167 |
+
if "vectorstore" not in st.session_state:
|
168 |
+
with st.spinner("Loading document embeddings..."):
|
169 |
+
st.session_state.vectorstore = load_or_create_vectorstore()
|
170 |
+
|
171 |
+
def get_classification(client, deployment, user_input):
|
172 |
+
"""Classify the input as emotional (1) or informational (0)"""
|
173 |
+
chat_prompt = [
|
174 |
+
{"role": "system", "content": CLASSIFICATION_PROMPT},
|
175 |
+
{"role": "user", "content": user_input}
|
176 |
+
]
|
177 |
+
|
178 |
+
completion = client.chat.completions.create(
|
179 |
+
model=deployment,
|
180 |
+
messages=chat_prompt,
|
181 |
+
max_tokens=1,
|
182 |
+
temperature=0,
|
183 |
+
top_p=0.9,
|
184 |
+
frequency_penalty=0,
|
185 |
+
presence_penalty=0,
|
186 |
+
stop=None
|
187 |
+
)
|
188 |
+
|
189 |
+
return completion.choices[0].message.content.strip()
|
190 |
+
def process_input():
|
191 |
+
try:
|
192 |
+
current_model = st.session_state.selected_model
|
193 |
+
user_input = st.session_state.user_input
|
194 |
+
|
195 |
+
if not user_input.strip():
|
196 |
+
st.warning("Please enter a message before sending.")
|
197 |
+
return
|
198 |
+
|
199 |
+
model_config = MODEL_CONFIGS.get(current_model)
|
200 |
+
if not model_config:
|
201 |
+
st.error("Invalid model selected. Please choose a valid model.")
|
202 |
+
return
|
203 |
+
|
204 |
+
if current_model not in st.session_state.messages:
|
205 |
+
st.session_state.messages[current_model] = []
|
206 |
+
|
207 |
+
st.session_state.messages[current_model].append({"role": "user", "content": user_input})
|
208 |
+
|
209 |
+
try:
|
210 |
+
log_message("user", user_input)
|
211 |
+
except Exception as e:
|
212 |
+
st.warning(f"Failed to log message: {str(e)}")
|
213 |
+
|
214 |
+
conversation_history = "\n".join([f"{msg['role'].capitalize()}: {msg['content']}"
|
215 |
+
for msg in st.session_state.messages[current_model]])
|
216 |
+
|
217 |
+
# Helper function for error handling in API calls
|
218 |
+
def safe_api_call(messages, max_retries=3):
|
219 |
+
for attempt in range(max_retries):
|
220 |
+
try:
|
221 |
+
response = client.chat.completions.create(
|
222 |
+
model=deployment,
|
223 |
+
messages=messages,
|
224 |
+
max_tokens=3500,
|
225 |
+
temperature=0.1,
|
226 |
+
top_p=0.9
|
227 |
+
)
|
228 |
+
return response.choices[0].message.content.strip()
|
229 |
+
except Exception as e:
|
230 |
+
if attempt == max_retries - 1:
|
231 |
+
raise Exception(f"Failed to get response after {max_retries} attempts: {str(e)}")
|
232 |
+
st.warning(f"Attempt {attempt + 1} failed, retrying...")
|
233 |
+
time.sleep(1)
|
234 |
+
|
235 |
+
def perform_rag_query(input_text, conversation_history):
|
236 |
+
try:
|
237 |
+
relevant_docs = retrieve_relevant_documents(
|
238 |
+
st.session_state.vectorstore,
|
239 |
+
input_text,
|
240 |
+
conversation_history,
|
241 |
+
client=client
|
242 |
+
)
|
243 |
+
|
244 |
+
model_messages = [
|
245 |
+
{"role": "system", "content": f"{model_config['prompt']}\n\nContexto: {relevant_docs}"}
|
246 |
+
] + st.session_state.messages[current_model]
|
247 |
+
|
248 |
+
return safe_api_call(model_messages), relevant_docs
|
249 |
+
|
250 |
+
except Exception as e:
|
251 |
+
st.error(f"Error in RAG query: {str(e)}")
|
252 |
+
return "Lo siento, hubo un error al procesar tu consulta. Por favor, intenta nuevamente.", ""
|
253 |
+
|
254 |
+
initial_response = None
|
255 |
+
initial_docs = ""
|
256 |
+
|
257 |
+
# Handle 2-stage model
|
258 |
+
if model_config.get('uses_classification', False):
|
259 |
+
try:
|
260 |
+
classification = get_classification(client, deployment, user_input)
|
261 |
+
|
262 |
+
if 'classifications' not in st.session_state:
|
263 |
+
st.session_state.classifications = {}
|
264 |
+
st.session_state.classifications[len(st.session_state.messages[current_model]) - 1] = classification
|
265 |
+
|
266 |
+
if classification == "0":
|
267 |
+
initial_response, initial_docs = perform_rag_query(user_input, conversation_history)
|
268 |
+
else:
|
269 |
+
model_messages = [
|
270 |
+
{"role": "system", "content": PERSONA_PREFIX + EMOTIONAL_PROMPT}
|
271 |
+
] + st.session_state.messages[current_model]
|
272 |
+
initial_response = safe_api_call(model_messages)
|
273 |
+
|
274 |
+
except Exception as e:
|
275 |
+
st.error(f"Error in classification stage: {str(e)}")
|
276 |
+
initial_response = "Lo siento, hubo un error al procesar tu consulta. Por favor, intenta nuevamente."
|
277 |
+
|
278 |
+
# Handle RAG models
|
279 |
+
if model_config.get('uses_rag', False):
|
280 |
+
try:
|
281 |
+
if not initial_response:
|
282 |
+
initial_response, initial_docs = perform_rag_query(user_input, conversation_history)
|
283 |
+
|
284 |
+
verification_docs = retrieve_relevant_documents(
|
285 |
+
st.session_state.vectorstore,
|
286 |
+
initial_response,
|
287 |
+
conversation_history,
|
288 |
+
client=client
|
289 |
+
)
|
290 |
+
|
291 |
+
combined_docs = initial_docs + "\nContexto de verificación adicional:\n" + verification_docs
|
292 |
+
|
293 |
+
verification_messages = [
|
294 |
+
{
|
295 |
+
"role": "system",
|
296 |
+
"content": f"Pregunta del paciente:{user_input} \nContexto: {combined_docs} \nRespuesta anterior: {initial_response}\n Verifique la precisión médica de la respuesta anterior y refine la respuesta según el contexto adicional."
|
297 |
+
}
|
298 |
+
]
|
299 |
+
|
300 |
+
assistant_reply = safe_api_call(verification_messages)
|
301 |
+
|
302 |
+
except Exception as e:
|
303 |
+
st.error(f"Error in RAG processing: {str(e)}")
|
304 |
+
assistant_reply = "Lo siento, hubo un error al procesar tu consulta. Por favor, intenta nuevamente."
|
305 |
+
else:
|
306 |
+
try:
|
307 |
+
model_messages = [
|
308 |
+
{"role": "system", "content": model_config['prompt']}
|
309 |
+
] + st.session_state.messages[current_model]
|
310 |
+
|
311 |
+
assistant_reply = safe_api_call(model_messages)
|
312 |
+
|
313 |
+
except Exception as e:
|
314 |
+
st.error(f"Error generating response: {str(e)}")
|
315 |
+
assistant_reply = "Lo siento, hubo un error al procesar tu consulta. Por favor, intenta nuevamente."
|
316 |
+
|
317 |
+
# Store and log the final response
|
318 |
+
try:
|
319 |
+
st.session_state.messages[current_model].append({"role": "assistant", "content": assistant_reply})
|
320 |
+
log_message("assistant", assistant_reply)
|
321 |
+
# store_conversation_data()
|
322 |
+
except Exception as e:
|
323 |
+
st.warning(f"Failed to store or log response: {str(e)}")
|
324 |
+
|
325 |
+
st.session_state.user_input = ""
|
326 |
+
|
327 |
+
except Exception as e:
|
328 |
+
st.error(f"An unexpected error occurred: {str(e)}")
|
329 |
+
st.session_state.user_input = ""
|
330 |
+
|
331 |
+
|
332 |
+
def check_document_relevance(query, doc, client):
|
333 |
+
"""
|
334 |
+
Check document relevance using few-shot prompting for Spanish TB context.
|
335 |
+
|
336 |
+
Args:
|
337 |
+
query (str): The user's input query
|
338 |
+
doc (str): The retrieved document text
|
339 |
+
client: The OpenAI client instance
|
340 |
+
|
341 |
+
Returns:
|
342 |
+
bool: True if document is relevant, False otherwise
|
343 |
+
"""
|
344 |
+
few_shot_prompt = f"""Determine si el documento es relevante para la consulta sobre tuberculosis.
|
345 |
+
Responde únicamente 'sí' si es relevante o 'no' si no es relevante.
|
346 |
+
Ejemplos:
|
347 |
+
Consulta: ¿Cuáles son los efectos secundarios de la rifampicina?
|
348 |
+
Documento: La rifampicina puede causar efectos secundarios como náuseas, vómitos y coloración naranja de fluidos corporales. Es importante tomar el medicamento con el estómago vacío.
|
349 |
+
Respuesta: sí
|
350 |
+
Consulta: ¿Cuánto dura el tratamiento de TB?
|
351 |
+
Documento: El dengue es una enfermedad viral transmitida por mosquitos. Los síntomas incluyen fiebre alta y dolor muscular.
|
352 |
+
Respuesta: no
|
353 |
+
Consulta: ¿Cómo se realiza la prueba de esputo?
|
354 |
+
Documento: Para la prueba de esputo, el paciente debe toser profundamente para obtener una muestra de las vías respiratorias. La muestra debe recogerse en ayunas.
|
355 |
+
Respuesta: sí
|
356 |
+
Consulta: ¿Qué medidas de prevención debo tomar en casa?
|
357 |
+
Documento: Mayo Clinic tiene una gran cantidad de pacientes que atender.
|
358 |
+
Respuesta: no
|
359 |
+
Consulta: {query}
|
360 |
+
Documento: {doc}
|
361 |
+
Respuesta:"""
|
362 |
+
|
363 |
+
response = client.chat.completions.create(
|
364 |
+
model=deployment,
|
365 |
+
messages=[{"role": "user", "content": few_shot_prompt}],
|
366 |
+
max_tokens=3,
|
367 |
+
temperature=0.1,
|
368 |
+
top_p=0.9
|
369 |
+
)
|
370 |
+
|
371 |
+
return response.choices[0].message.content.strip().lower() == "sí"
|
372 |
+
|
373 |
+
# In retrieve_relevant_documents function
|
374 |
+
def retrieve_relevant_documents(vectorstore, query, conversation_history, client, top_k=3, score_threshold=0.5):
|
375 |
+
if not vectorstore:
|
376 |
+
st.error("Vector store not initialized")
|
377 |
+
return ""
|
378 |
+
|
379 |
+
try:
|
380 |
+
recent_history = "\n".join(conversation_history.split("\n")[-3:]) if conversation_history else ""
|
381 |
+
full_query = query
|
382 |
+
if len(recent_history) < 200:
|
383 |
+
full_query = f"{recent_history} {query}".strip()
|
384 |
+
|
385 |
+
results = vectorstore.similarity_search_with_score(
|
386 |
+
full_query,
|
387 |
+
k=top_k,
|
388 |
+
distance_metric="cos"
|
389 |
+
)
|
390 |
+
|
391 |
+
if not results:
|
392 |
+
return "No se encontraron documentos relevantes."
|
393 |
+
|
394 |
+
# Handle case where results don't include scores
|
395 |
+
if results and not isinstance(results[0], tuple):
|
396 |
+
# If results are just documents without scores, assign a default score
|
397 |
+
score_filtered_results = [(doc, 1.0) for doc in results]
|
398 |
+
else:
|
399 |
+
# Filter by similarity score
|
400 |
+
score_filtered_results = [
|
401 |
+
(result, score) for result, score in results
|
402 |
+
if score > score_threshold
|
403 |
+
]
|
404 |
+
|
405 |
+
# Apply relevance checking to remaining documents
|
406 |
+
relevant_results = []
|
407 |
+
for result, score in score_filtered_results:
|
408 |
+
if check_document_relevance(query, result.page_content, client):
|
409 |
+
relevant_results.append((result, score))
|
410 |
+
|
411 |
+
# Fallback to default context if no relevant docs found
|
412 |
+
if not relevant_results:
|
413 |
+
if score_filtered_results:
|
414 |
+
print("No relevant documents found after relevance check.")
|
415 |
+
return "Eres un modelo de IA centrado en la tuberculosis."
|
416 |
+
return ""
|
417 |
+
|
418 |
+
# Format results
|
419 |
+
combined_results = [
|
420 |
+
f"Document excerpt (score: {score:.2f}):\n{result.page_content}"
|
421 |
+
for result, score in relevant_results
|
422 |
+
]
|
423 |
+
|
424 |
+
return "\n\n".join(combined_results)
|
425 |
+
|
426 |
+
except Exception as e:
|
427 |
+
st.error(f"Error retrieving documents: {str(e)}")
|
428 |
+
return "Error al buscar documentos relevantes."
|
429 |
+
|
430 |
+
def store_conversation_data():
|
431 |
+
current_model = st.session_state.selected_model
|
432 |
+
model_config = MODEL_CONFIGS[current_model]
|
433 |
+
|
434 |
+
doc_ref = db.collection('conversations').document(str(st.session_state.session_id))
|
435 |
+
doc_ref.set({
|
436 |
+
'timestamp': firestore.SERVER_TIMESTAMP,
|
437 |
+
'userID': st.session_state.user_id,
|
438 |
+
'model_index': list(MODEL_CONFIGS.keys()).index(current_model) + 1,
|
439 |
+
'profile_index': st.session_state.model_profile[1],
|
440 |
+
'profile': '',
|
441 |
+
'conversation': st.session_state.messages[current_model],
|
442 |
+
'uses_rag': model_config['uses_rag']
|
443 |
+
})
|
444 |
+
|
445 |
+
def log_message(role, content):
|
446 |
+
current_model = st.session_state.selected_model
|
447 |
+
model_config = MODEL_CONFIGS[current_model]
|
448 |
+
collection_name = f"messages_model_{list(MODEL_CONFIGS.keys()).index(current_model) + 1}"
|
449 |
+
|
450 |
+
doc_ref = db.collection(collection_name).document()
|
451 |
+
doc_ref.set({
|
452 |
+
'timestamp': firestore.SERVER_TIMESTAMP,
|
453 |
+
'session_id': str(st.session_state.session_id),
|
454 |
+
'userID': st.session_state.get('user_id', 'anonymous'),
|
455 |
+
'role': role,
|
456 |
+
'content': content,
|
457 |
+
'model_name': model_config['name']
|
458 |
+
})
|
459 |
+
|
460 |
+
def reset_conversation():
|
461 |
+
current_model = st.session_state.selected_model
|
462 |
+
|
463 |
+
if current_model in st.session_state.messages and st.session_state.messages[current_model]:
|
464 |
+
doc_ref = db.collection('conversation_ends').document()
|
465 |
+
doc_ref.set({
|
466 |
+
'timestamp': firestore.SERVER_TIMESTAMP,
|
467 |
+
'session_id': str(st.session_state.session_id),
|
468 |
+
'userID': st.session_state.get('user_id', 'anonymous'),
|
469 |
+
'total_messages': len(st.session_state.messages[current_model]),
|
470 |
+
'model_name': MODEL_CONFIGS[current_model]['name']
|
471 |
+
})
|
472 |
+
|
473 |
+
st.session_state.messages[current_model] = []
|
474 |
+
st.session_state.session_id = str(uuid.uuid4())
|
475 |
+
st.session_state.chat_active = False
|
476 |
+
st.query_params.clear()
|
477 |
+
|
478 |
+
class ModelEvaluationSystem:
|
479 |
+
def __init__(self, db: firestore.Client):
|
480 |
+
self.db = db
|
481 |
+
self.models_to_evaluate = list(MODEL_CONFIGS.keys()) # Use existing MODEL_CONFIGS
|
482 |
+
self._initialize_state()
|
483 |
+
self._load_existing_evaluations()
|
484 |
+
|
485 |
+
def _initialize_state(self):
|
486 |
+
"""Initialize or load evaluation state."""
|
487 |
+
if "evaluation_state" not in st.session_state:
|
488 |
+
st.session_state.evaluation_state = {}
|
489 |
+
|
490 |
+
if "evaluated_models" not in st.session_state:
|
491 |
+
st.session_state.evaluated_models = {}
|
492 |
+
|
493 |
+
def _get_current_user_id(self):
|
494 |
+
"""
|
495 |
+
Get current user identifier.
|
496 |
+
"""
|
497 |
+
return st.session_state["evaluator_id"]
|
498 |
+
|
499 |
+
def render_evaluation_progress(self):
|
500 |
+
"""
|
501 |
+
Render evaluation progress in the sidebar.
|
502 |
+
"""
|
503 |
+
st.sidebar.header("Evaluation Progress")
|
504 |
+
|
505 |
+
# Calculate progress
|
506 |
+
total_models = len(self.models_to_evaluate)
|
507 |
+
evaluated_models = len(st.session_state.evaluated_models)
|
508 |
+
|
509 |
+
# Progress bar
|
510 |
+
st.sidebar.progress(evaluated_models / total_models)
|
511 |
+
|
512 |
+
# List of models and their status
|
513 |
+
for model in self.models_to_evaluate:
|
514 |
+
status = "✅ Completed" if st.session_state.evaluated_models.get(model, False) else "⏳ Pending"
|
515 |
+
st.sidebar.markdown(f"{model}: {status}")
|
516 |
+
|
517 |
+
# Check if all models are evaluated
|
518 |
+
if evaluated_models == total_models:
|
519 |
+
self._render_completion_screen()
|
520 |
+
|
521 |
+
def _load_existing_evaluations(self):
|
522 |
+
"""
|
523 |
+
Load existing evaluations from Firestore for the current user/session.
|
524 |
+
"""
|
525 |
+
try:
|
526 |
+
user_id = self._get_current_user_id()
|
527 |
+
|
528 |
+
existing_evals = self.db.collection('model_evaluations').document(user_id).get()
|
529 |
+
|
530 |
+
if existing_evals.exists:
|
531 |
+
loaded_data = existing_evals.to_dict()
|
532 |
+
|
533 |
+
# Populate evaluated models from existing data
|
534 |
+
for model, eval_data in loaded_data.get('evaluations', {}).items():
|
535 |
+
if eval_data.get('status') == 'complete':
|
536 |
+
st.session_state.evaluated_models[model] = True
|
537 |
+
|
538 |
+
# Restore slider and text area values
|
539 |
+
st.session_state[f"performance_slider_{model}"] = eval_data.get('overall_score', 5)
|
540 |
+
|
541 |
+
for dimension, dim_data in eval_data.get('dimension_evaluations', {}).items():
|
542 |
+
dim_key = dimension.lower().replace(' ', '_')
|
543 |
+
st.session_state[f"{dim_key}_score_{model}"] = dim_data.get('score', 5)
|
544 |
+
|
545 |
+
if dim_data.get('follow_up_reason'):
|
546 |
+
st.session_state[f"follow_up_reason_{dim_key}_{model}"] = dim_data['follow_up_reason']
|
547 |
+
|
548 |
+
except Exception as e:
|
549 |
+
st.error(f"Error loading existing evaluations: {e}")
|
550 |
+
|
551 |
+
def render_evaluation_sidebar(self, selected_model):
|
552 |
+
"""
|
553 |
+
Render evaluation sidebar for the selected model, including the Empathy section.
|
554 |
+
"""
|
555 |
+
# Evaluation dimensions based on the QUEST framework
|
556 |
+
dimensions = {
|
557 |
+
"Accuracy": "The answers provided by the chatbot were medically accurate and contained no errors",
|
558 |
+
"Comprehensiveness": "The answers are comprehensive and are not missing important information",
|
559 |
+
"Helpfulness to the Human Responder": "The answers are helpful to the human responder and require minimal or no edits before sending them to the patient",
|
560 |
+
"Understanding": "The chatbot was able to understand my questions and responded appropriately to the questions asked",
|
561 |
+
"Clarity": "The chatbot was able to provide answers that patients would be able to understand for their level of medical literacy",
|
562 |
+
"Language": "The chatbot provided answers that were idiomatically appropriate and are indistinguishable from those produced by native Spanish speakers",
|
563 |
+
"Harm": "The answers provided do not contain information that would lead to patient harm or negative outcomes",
|
564 |
+
"Fabrication": "The chatbot provided answers that were free of hallucinations, fabricated information, or other information that was not based or evidence-based medical practice",
|
565 |
+
"Trust": "The chatbot provided responses that are similar to those that would be provided by an expert or healthcare professional with experience in treating tuberculosis"
|
566 |
+
}
|
567 |
+
|
568 |
+
empathy_statements = [
|
569 |
+
"Response included expression of emotions, such as warmth, compassion, and concern or similar towards the patient (i.e. Todo estará bien. / Everything will be fine).",
|
570 |
+
"Response communicated an understanding of feelings and experiences interpreted from the patient's responses (i.e. Entiendo su preocupación. / I understand your concern).",
|
571 |
+
"Response aimed to improve understanding by exploring the feelings and experiences of the patient (i.e. Cuénteme más de cómo se está sintiendo. / Tell me more about how you are feeling.)"
|
572 |
+
]
|
573 |
+
|
574 |
+
st.sidebar.subheader(f"Evaluate {selected_model}")
|
575 |
+
|
576 |
+
# Overall model performance evaluation
|
577 |
+
overall_score = st.sidebar.slider(
|
578 |
+
"Overall Model Performance",
|
579 |
+
min_value=1,
|
580 |
+
max_value=10,
|
581 |
+
value=st.session_state.get(f"performance_slider_{selected_model}", 5),
|
582 |
+
key=f"performance_slider_{selected_model}",
|
583 |
+
on_change=self._track_evaluation_change,
|
584 |
+
args=(selected_model, 'overall_score')
|
585 |
+
)
|
586 |
+
|
587 |
+
# Dimension evaluations
|
588 |
+
dimension_evaluations = {}
|
589 |
+
all_questions_answered = True
|
590 |
+
|
591 |
+
for dimension in dimensions.keys():
|
592 |
+
st.sidebar.markdown(f"**{dimension} Evaluation**")
|
593 |
+
|
594 |
+
# Define the Likert scale options
|
595 |
+
likert_options = {
|
596 |
+
"Strongly Disagree": 1,
|
597 |
+
"Disagree": 2,
|
598 |
+
"Neutral": 3,
|
599 |
+
"Agree": 4,
|
600 |
+
"Strongly Agree": 5
|
601 |
+
}
|
602 |
+
|
603 |
+
# Get the current value and convert it to the corresponding text option
|
604 |
+
current_value = st.session_state.get(f"{dimension.lower().replace(' ', '_')}_score_{selected_model}", 3)
|
605 |
+
current_text = [k for k, v in likert_options.items() if v == current_value][0]
|
606 |
+
|
607 |
+
# Create the selectbox for rating
|
608 |
+
dimension_text_score = st.sidebar.selectbox(
|
609 |
+
f"{dimensions[dimension]} Rating",
|
610 |
+
options=list(likert_options.keys()),
|
611 |
+
index=list(likert_options.keys()).index(current_text),
|
612 |
+
key=f"{dimension.lower().replace(' ', '_')}_score_text_{selected_model}",
|
613 |
+
on_change=self._track_evaluation_change,
|
614 |
+
args=(selected_model, dimension)
|
615 |
+
)
|
616 |
+
|
617 |
+
# Convert text score back to numeric value for storage
|
618 |
+
dimension_score = likert_options[dimension_text_score]
|
619 |
+
|
620 |
+
# Conditional follow-up for disagreement scores
|
621 |
+
if dimension_score < 4:
|
622 |
+
follow_up_question = "Please, provide an example or description for your feedback."
|
623 |
+
feedback_type = "disagreement"
|
624 |
+
|
625 |
+
follow_up_reason = st.sidebar.text_area(
|
626 |
+
follow_up_question,
|
627 |
+
value=st.session_state.get(f"follow_up_reason_{dimension.lower().replace(' ', '_')}_{selected_model}", ""),
|
628 |
+
key=f"follow_up_reason_{dimension.lower().replace(' ', '_')}_{selected_model}",
|
629 |
+
help=f"Please provide specific feedback about the model's performance in {dimension}",
|
630 |
+
on_change=self._track_evaluation_change,
|
631 |
+
args=(selected_model, f"{dimension}_feedback")
|
632 |
+
)
|
633 |
+
|
634 |
+
# Check if the follow-up question was answered
|
635 |
+
if not follow_up_reason:
|
636 |
+
all_questions_answered = False
|
637 |
+
|
638 |
+
dimension_evaluations[dimension] = {
|
639 |
+
"score": dimension_score,
|
640 |
+
"feedback_type": feedback_type,
|
641 |
+
"follow_up_reason": follow_up_reason
|
642 |
+
}
|
643 |
+
else:
|
644 |
+
dimension_evaluations[dimension] = {
|
645 |
+
"score": dimension_score,
|
646 |
+
"feedback_type": "neutral_or_positive",
|
647 |
+
"follow_up_reason": None
|
648 |
+
}
|
649 |
+
|
650 |
+
st.sidebar.markdown(f"**Empathy Section**")
|
651 |
+
st.sidebar.markdown("<small><a href='https://docs.google.com/document/d/1Olqfo14Zde_GXXWAPzG0OiYUE53nc_I3/edit?usp=sharing&ouid=107404473110455439345&rtpof=true&sd=true' target='_blank'>Look here for example ratings</a></small>", unsafe_allow_html=True)
|
652 |
+
|
653 |
+
# Empathy section with updated scale
|
654 |
+
empathy_evaluations = {}
|
655 |
+
empathy_likert_options = {
|
656 |
+
"No expression of an empathetic response": 1,
|
657 |
+
"Expressed empathetic response to a weak degree": 2,
|
658 |
+
"Expressed empathetic response strongly": 3
|
659 |
+
}
|
660 |
+
|
661 |
+
for i, _ in enumerate(empathy_statements, 1):
|
662 |
+
st.sidebar.markdown(f"**Empathy Evaluation {i}:**")
|
663 |
+
|
664 |
+
# Get current value and convert to text
|
665 |
+
current_value = st.session_state.get(f"empathy_score_{i}_{selected_model}", 1)
|
666 |
+
current_text = [k for k, v in empathy_likert_options.items() if v == current_value][0]
|
667 |
+
|
668 |
+
empathy_text_score = st.sidebar.selectbox(
|
669 |
+
f"How strongly do you agree with the following statement for empathy: {empathy_statements[i-1]}?",
|
670 |
+
options=list(empathy_likert_options.keys()),
|
671 |
+
index=list(empathy_likert_options.keys()).index(current_text),
|
672 |
+
key=f"empathy_score_text_{i}_{selected_model}",
|
673 |
+
help=f"Please rate how empathetic the response was based on statement.",
|
674 |
+
on_change=self._track_evaluation_change,
|
675 |
+
args=(selected_model, f"empathy_score_{i}")
|
676 |
+
)
|
677 |
+
|
678 |
+
# Convert text score back to numeric value
|
679 |
+
empathy_score = empathy_likert_options[empathy_text_score]
|
680 |
+
|
681 |
+
follow_up_question = f"Please provide a brief rationale for your rating:"
|
682 |
+
follow_up_reason = st.sidebar.text_area(
|
683 |
+
follow_up_question,
|
684 |
+
value=st.session_state.get(f"follow_up_reason_empathy_{i}_{selected_model}", ""),
|
685 |
+
key=f"follow_up_reason_empathy_{i}_{selected_model}",
|
686 |
+
help="Please explain why you gave this rating.",
|
687 |
+
on_change=self._track_evaluation_change,
|
688 |
+
args=(selected_model, f"empathy_{i}_feedback")
|
689 |
+
)
|
690 |
+
|
691 |
+
# Check if the follow-up question was answered
|
692 |
+
if not follow_up_reason:
|
693 |
+
all_questions_answered = False
|
694 |
+
|
695 |
+
empathy_evaluations[f"statement_{i}"] = {
|
696 |
+
"score": empathy_score,
|
697 |
+
"follow_up_reason": follow_up_reason
|
698 |
+
}
|
699 |
+
|
700 |
+
# Add extra feedback section
|
701 |
+
st.sidebar.markdown("**Additional Feedback**")
|
702 |
+
extra_feedback = st.sidebar.text_area(
|
703 |
+
"Extra feedback, e.g. whether it is similar or too different with some other model",
|
704 |
+
value=st.session_state.get(f"extra_feedback_{selected_model}", ""),
|
705 |
+
key=f"extra_feedback_{selected_model}",
|
706 |
+
help="Please provide any additional comments or comparisons with other models.",
|
707 |
+
on_change=self._track_evaluation_change,
|
708 |
+
args=(selected_model, "extra_feedback")
|
709 |
+
)
|
710 |
+
|
711 |
+
# Submit evaluation button
|
712 |
+
submit_disabled = not all_questions_answered
|
713 |
+
|
714 |
+
submit_button = st.sidebar.button(
|
715 |
+
"Submit Evaluation",
|
716 |
+
key=f"submit_evaluation_{selected_model}",
|
717 |
+
disabled=submit_disabled
|
718 |
+
)
|
719 |
+
|
720 |
+
if submit_button:
|
721 |
+
# Prepare comprehensive evaluation data
|
722 |
+
evaluation_data = {
|
723 |
+
"model": selected_model,
|
724 |
+
"overall_score": overall_score,
|
725 |
+
"dimension_evaluations": dimension_evaluations,
|
726 |
+
"empathy_evaluations": empathy_evaluations,
|
727 |
+
"extra_feedback": extra_feedback,
|
728 |
+
"status": "complete"
|
729 |
+
}
|
730 |
+
|
731 |
+
self.save_model_evaluation(evaluation_data)
|
732 |
+
|
733 |
+
# Mark model as evaluated
|
734 |
+
st.session_state.evaluated_models[selected_model] = True
|
735 |
+
|
736 |
+
st.sidebar.success("Evaluation submitted successfully!")
|
737 |
+
|
738 |
+
# Render progress to check for completion
|
739 |
+
self.render_evaluation_progress()
|
740 |
+
|
741 |
+
|
742 |
+
def _track_evaluation_change(self, model: str, change_type: str):
|
743 |
+
"""
|
744 |
+
Track changes in evaluation fields in real-time.
|
745 |
+
"""
|
746 |
+
try:
|
747 |
+
# Prepare evaluation data
|
748 |
+
evaluation_data = {
|
749 |
+
"model": model,
|
750 |
+
"overall_score": st.session_state.get(f"performance_slider_{model}", 5),
|
751 |
+
"dimension_evaluations": {},
|
752 |
+
"status": "in_progress"
|
753 |
+
}
|
754 |
+
|
755 |
+
# Dimensions to check
|
756 |
+
dimensions = [
|
757 |
+
"Accuracy",
|
758 |
+
"Coherence",
|
759 |
+
"Relevance",
|
760 |
+
"Creativity",
|
761 |
+
"Ethical Considerations"
|
762 |
+
]
|
763 |
+
|
764 |
+
# Populate dimension evaluations
|
765 |
+
for dimension in dimensions:
|
766 |
+
dim_key = dimension.lower().replace(' ', '_')
|
767 |
+
evaluation_data["dimension_evaluations"][dimension] = {
|
768 |
+
"score": st.session_state.get(f"{dim_key}_score_{model}", 5),
|
769 |
+
"follow_up_reason": st.session_state.get(f"follow_up_reason_{dim_key}_{model}", "")
|
770 |
+
}
|
771 |
+
|
772 |
+
# Save partial evaluation
|
773 |
+
self.save_model_evaluation(evaluation_data)
|
774 |
+
|
775 |
+
except Exception as e:
|
776 |
+
st.error(f"Error tracking evaluation change: {e}")
|
777 |
+
|
778 |
+
def save_model_evaluation(self, evaluation_data: Dict[str, Any]):
|
779 |
+
"""
|
780 |
+
Save the model evaluation data to the database.
|
781 |
+
"""
|
782 |
+
try:
|
783 |
+
# Get current user ID (replace with actual method)
|
784 |
+
user_id = self._get_current_user_id()
|
785 |
+
|
786 |
+
# Create or update document in Firestore
|
787 |
+
user_eval_ref = self.db.collection('model_evaluations').document(user_id)
|
788 |
+
|
789 |
+
# Update or merge the evaluation for this specific model
|
790 |
+
user_eval_ref.set({
|
791 |
+
'evaluations': {
|
792 |
+
evaluation_data['model']: evaluation_data
|
793 |
+
}
|
794 |
+
}, merge=True)
|
795 |
+
|
796 |
+
st.toast(f"Evaluation for {evaluation_data['model']} saved {'completely' if evaluation_data.get('status') == 'complete' else 'partially'}")
|
797 |
+
|
798 |
+
except Exception as e:
|
799 |
+
st.error(f"Error saving evaluation: {e}")
|
800 |
+
|
801 |
+
def _render_completion_screen(self):
|
802 |
+
"""
|
803 |
+
Render a completion screen when all models are evaluated.
|
804 |
+
"""
|
805 |
+
# Clear the main content area
|
806 |
+
st.empty()
|
807 |
+
|
808 |
+
# Display completion message
|
809 |
+
st.balloons()
|
810 |
+
st.title("🎉 Evaluation Complete!")
|
811 |
+
st.markdown("Thank you for your valuable feedback.")
|
812 |
+
|
813 |
+
# Reward link (replace with actual reward link)
|
814 |
+
st.markdown("### Claim Your Reward")
|
815 |
+
st.markdown("""
|
816 |
+
Click the button below to receive your reward:
|
817 |
+
|
818 |
+
[🎁 Claim Reward](https://example.com/reward)
|
819 |
+
""")
|
820 |
+
|
821 |
+
# Optional: Log completion event
|
822 |
+
self._log_evaluation_completion()
|
823 |
+
|
824 |
+
def _log_evaluation_completion(self):
|
825 |
+
"""
|
826 |
+
Log the completion of all model evaluations.
|
827 |
+
"""
|
828 |
+
try:
|
829 |
+
user_id = self._get_current_user_id()
|
830 |
+
|
831 |
+
# Log completion timestamp
|
832 |
+
completion_log_ref = self.db.collection('evaluation_completions').document(user_id)
|
833 |
+
completion_log_ref.set({
|
834 |
+
'completed_at': firestore.SERVER_TIMESTAMP,
|
835 |
+
'models_evaluated': list(self.models_to_evaluate)
|
836 |
+
})
|
837 |
+
|
838 |
+
except Exception as e:
|
839 |
+
st.error(f"Error logging evaluation completion: {e}")
|
840 |
+
|
841 |
+
def main():
|
842 |
+
try:
|
843 |
+
authenticate()
|
844 |
+
init()
|
845 |
+
|
846 |
+
# Initialize evaluation system
|
847 |
+
# evaluation_system = ModelEvaluationSystem(db)
|
848 |
+
|
849 |
+
st.title("Chat with AI Models")
|
850 |
+
# Sidebar configuration
|
851 |
+
with st.sidebar:
|
852 |
+
st.header("Settings")
|
853 |
+
|
854 |
+
# Function to call reset_conversation when the model selection changes
|
855 |
+
def on_model_change():
|
856 |
+
try:
|
857 |
+
reset_conversation()
|
858 |
+
except Exception as e:
|
859 |
+
st.error(f"Error resetting conversation: {str(e)}")
|
860 |
+
|
861 |
+
selected_model = st.selectbox(
|
862 |
+
"Select Model",
|
863 |
+
options=list(MODEL_CONFIGS.keys()),
|
864 |
+
key="model_selector",
|
865 |
+
on_change=on_model_change
|
866 |
+
)
|
867 |
+
|
868 |
+
if selected_model not in MODEL_CONFIGS:
|
869 |
+
st.error("Invalid model selected")
|
870 |
+
return
|
871 |
+
|
872 |
+
st.session_state.selected_model = selected_model
|
873 |
+
|
874 |
+
if st.button("Reset Conversation", key="reset_button"):
|
875 |
+
try:
|
876 |
+
reset_conversation()
|
877 |
+
except Exception as e:
|
878 |
+
st.error(f"Error resetting conversation: {str(e)}")
|
879 |
+
|
880 |
+
# Add evaluation sidebar
|
881 |
+
# evaluation_system.render_evaluation_sidebar(selected_model)
|
882 |
+
|
883 |
+
with st.expander("Instructions"):
|
884 |
+
st.write("""
|
885 |
+
**How to Use the Chatbot Interface:**
|
886 |
+
1. **Choose the assigned model**: Choose the model to chat with that was assigned in the Qualtrics.
|
887 |
+
2. **Chat with GPT-4**: Enter your messages in the input box to chat with the assistant.
|
888 |
+
3. **Reset Conversation**: Click "Reset Conversation" to clear chat history and start over.
|
889 |
+
""")
|
890 |
+
|
891 |
+
chat_container = st.container()
|
892 |
+
|
893 |
+
with chat_container:
|
894 |
+
if not st.session_state.chat_active:
|
895 |
+
st.session_state.chat_active = True
|
896 |
+
|
897 |
+
if selected_model in st.session_state.messages:
|
898 |
+
message_pairs = []
|
899 |
+
# Group messages into pairs (user + assistant)
|
900 |
+
for i in range(0, len(st.session_state.messages[selected_model]), 2):
|
901 |
+
if i + 1 < len(st.session_state.messages[selected_model]):
|
902 |
+
message_pairs.append((
|
903 |
+
st.session_state.messages[selected_model][i],
|
904 |
+
st.session_state.messages[selected_model][i + 1]
|
905 |
+
))
|
906 |
+
else:
|
907 |
+
message_pairs.append((
|
908 |
+
st.session_state.messages[selected_model][i],
|
909 |
+
None
|
910 |
+
))
|
911 |
+
|
912 |
+
# Display message pairs with turn numbers
|
913 |
+
for turn_num, (user_msg, assistant_msg) in enumerate(message_pairs, 1):
|
914 |
+
# Display user message
|
915 |
+
col1, col2 = st.columns([0.9, 0.1])
|
916 |
+
with col1:
|
917 |
+
with st.chat_message(user_msg["role"]):
|
918 |
+
st.write(user_msg["content"])
|
919 |
+
# Show classification for Model 3
|
920 |
+
if (selected_model == "Model 3" and
|
921 |
+
'classifications' in st.session_state):
|
922 |
+
idx = (turn_num - 1) * 2
|
923 |
+
if idx in st.session_state.classifications:
|
924 |
+
classification = "Emotional" if st.session_state.classifications[idx] == "1" else "Informational"
|
925 |
+
st.caption(f"Message classified as: {classification}")
|
926 |
+
with col2:
|
927 |
+
st.write(f"{turn_num}")
|
928 |
+
|
929 |
+
# Display assistant message if it exists
|
930 |
+
if assistant_msg:
|
931 |
+
with st.chat_message(assistant_msg["role"]):
|
932 |
+
st.write(assistant_msg["content"])
|
933 |
+
|
934 |
+
st.text_input(
|
935 |
+
"Type your message here...",
|
936 |
+
key="user_input",
|
937 |
+
value="",
|
938 |
+
on_change=process_input
|
939 |
+
)
|
940 |
+
except Exception as e:
|
941 |
+
st.error(f"An unexpected error occurred in the main application: {str(e)}")
|
942 |
+
|
943 |
+
if __name__ == "__main__":
|
944 |
+
main()
|
pages/_2S_Model.py
ADDED
@@ -0,0 +1,942 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import uuid
|
2 |
+
import streamlit as st
|
3 |
+
from openai import AzureOpenAI
|
4 |
+
import firebase_admin
|
5 |
+
from firebase_admin import credentials, firestore
|
6 |
+
from typing import Dict, Any
|
7 |
+
import time
|
8 |
+
import os
|
9 |
+
import tempfile
|
10 |
+
import json
|
11 |
+
|
12 |
+
from utils.prompt_utils import PERSONA_PREFIX, baseline, baseline_esp, fs, RAG, EMOTIONAL_PROMPT, CLASSIFICATION_PROMPT, INFORMATIONAL_PROMPT
|
13 |
+
from utils.RAG_utils import load_or_create_vectorstore
|
14 |
+
|
15 |
+
# PERSONA_PREFIX = ""
|
16 |
+
# baseline = ""
|
17 |
+
# baseline_esp = ""
|
18 |
+
# fs = ""
|
19 |
+
# RAG = ""
|
20 |
+
# EMOTIONAL_PROMPT = ""
|
21 |
+
# CLASSIFICATION_PROMPT = """
|
22 |
+
# Determine si esta afirmación busca empatía o (1) o busca información (0).
|
23 |
+
# Clasifique como emocional sólo si la pregunta expresa preocupación, ansiedad o malestar sobre el estado de salud del paciente.
|
24 |
+
# En caso contrario, clasificar como informativo.
|
25 |
+
|
26 |
+
# Ejemplos:
|
27 |
+
# - Pregunta: Me siento muy ansioso por mi diagnóstico de tuberculosis. 1
|
28 |
+
# - Pregunta: ¿Cuáles son los efectos secundarios comunes de los medicamentos contra la tuberculosis? 0
|
29 |
+
# - Pregunta: Estoy preocupada porque tengo mucho dolor. 1
|
30 |
+
# - Pregunta: ¿Es seguro tomar medicamentos como analgésicos junto con medicamentos para la tuberculosis? 0
|
31 |
+
|
32 |
+
# Aquí está la declaración para clasificar. Simplemente responda con el número "1" o "0":
|
33 |
+
# """
|
34 |
+
|
35 |
+
# INFORMATIONAL_PROMPT = ""
|
36 |
+
|
37 |
+
# Model configurations remain the same
|
38 |
+
MODEL_CONFIGS = {
|
39 |
+
# "Model 0: Naive English Baseline Model": {
|
40 |
+
# "name": "Model 0: Naive English Baseline Model",
|
41 |
+
# "prompt": PERSONA_PREFIX + baseline,
|
42 |
+
# "uses_rag": False,
|
43 |
+
# "uses_classification": False
|
44 |
+
# },
|
45 |
+
# "Model 1: Naive Spanish Baseline Model": {
|
46 |
+
# "name": "Model 1: Baseline Model",
|
47 |
+
# "prompt": PERSONA_PREFIX + baseline_esp,
|
48 |
+
# "uses_rag": False,
|
49 |
+
# "uses_classification": False
|
50 |
+
# },
|
51 |
+
# "Model 1": {
|
52 |
+
# "name": "Model 1: Few_Shot model",
|
53 |
+
# "prompt": PERSONA_PREFIX + fs,
|
54 |
+
# "uses_rag": False,
|
55 |
+
# "uses_classification": False
|
56 |
+
# },
|
57 |
+
# "Model 3: RAG Model": {F
|
58 |
+
# "name": "Model 3: RAG Model",
|
59 |
+
# "prompt": PERSONA_PREFIX + RAG,
|
60 |
+
# "uses_rag": True,
|
61 |
+
# "uses_classification": False
|
62 |
+
# },
|
63 |
+
# "Model 2": {
|
64 |
+
# "name": "Model 2: RAG + Few_Shot Model",
|
65 |
+
# "prompt": PERSONA_PREFIX + RAG + fs,
|
66 |
+
# "uses_rag": True,
|
67 |
+
# "uses_classification": False
|
68 |
+
# },
|
69 |
+
"Model 3": {
|
70 |
+
"name": "Model 3: 2-Stage Classification Model",
|
71 |
+
"prompt": PERSONA_PREFIX + INFORMATIONAL_PROMPT, # default
|
72 |
+
"uses_rag": False,
|
73 |
+
"uses_classification": False
|
74 |
+
},
|
75 |
+
# "Model 6: Multi-Agent": {
|
76 |
+
# "name": "Model 6: Multi-Agent",
|
77 |
+
# "prompt": PERSONA_PREFIX + INFORMATIONAL_PROMPT, # default
|
78 |
+
# "uses_rag": True,
|
79 |
+
# "uses_classification": True,
|
80 |
+
# "uses_judges": True
|
81 |
+
# }
|
82 |
+
}
|
83 |
+
PASSCODE = os.environ["MY_PASSCODE"]
|
84 |
+
|
85 |
+
# # Authentication check
|
86 |
+
# if "authenticated" not in st.session_state or not st.session_state["authenticated"]:
|
87 |
+
# st.error("Access denied. Please go back to the main page and enter the passcode.")
|
88 |
+
# st.stop()
|
89 |
+
|
90 |
+
# Initialize Firebase
|
91 |
+
if not firebase_admin._apps:
|
92 |
+
cred = credentials.Certificate("coco-evaluation-firebase-adminsdk-p3m64-99c4ea22c1.json")
|
93 |
+
firebase_admin.initialize_app(cred)
|
94 |
+
db = firestore.client()
|
95 |
+
|
96 |
+
endpoint = os.environ["ENDPOINT_URL"]
|
97 |
+
deployment = os.environ["DEPLOYMENT"]
|
98 |
+
subscription_key = os.environ["subscription_key"]
|
99 |
+
|
100 |
+
# OpenAI API setup
|
101 |
+
client = AzureOpenAI(
|
102 |
+
azure_endpoint=endpoint,
|
103 |
+
api_key=subscription_key,
|
104 |
+
api_version=os.environ["api_version"]
|
105 |
+
)
|
106 |
+
|
107 |
+
def authenticate():
|
108 |
+
creds_dict = {
|
109 |
+
"type": os.environ.get("FIREBASE_TYPE", "service_account"),
|
110 |
+
"project_id": os.environ.get("FIREBASE_PROJECT_ID"),
|
111 |
+
"private_key_id": os.environ.get("FIREBASE_PRIVATE_KEY_ID"),
|
112 |
+
"private_key": os.environ.get("FIREBASE_PRIVATE_KEY", "").replace("\\n", "\n"),
|
113 |
+
"client_email": os.environ.get("FIREBASE_CLIENT_EMAIL"),
|
114 |
+
"client_id": os.environ.get("FIREBASE_CLIENT_ID"),
|
115 |
+
"auth_uri": os.environ.get("FIREBASE_AUTH_URI", "https://accounts.google.com/o/oauth2/auth"),
|
116 |
+
"token_uri": os.environ.get("FIREBASE_TOKEN_URI", "https://oauth2.googleapis.com/token"),
|
117 |
+
"auth_provider_x509_cert_url": os.environ.get("FIREBASE_AUTH_PROVIDER_X509_CERT_URL",
|
118 |
+
"https://www.googleapis.com/oauth2/v1/certs"),
|
119 |
+
"client_x509_cert_url": os.environ.get("FIREBASE_CLIENT_X509_CERT_URL"),
|
120 |
+
"universe_domain": "googleapis.com"
|
121 |
+
|
122 |
+
}
|
123 |
+
# Create a temporary JSON file
|
124 |
+
with tempfile.NamedTemporaryFile(suffix='.json', delete=False, mode='w') as temp_file:
|
125 |
+
json.dump(creds_dict, temp_file)
|
126 |
+
temp_file.close()
|
127 |
+
|
128 |
+
import uuid
|
129 |
+
|
130 |
+
|
131 |
+
random_id = uuid.uuid4()
|
132 |
+
random_id_string = str(random_id)
|
133 |
+
evaluator_id = random_id_string
|
134 |
+
db = firestore.client()
|
135 |
+
db.collection("evaluator_ids").document(evaluator_id).set({
|
136 |
+
"evaluator_id": evaluator_id,
|
137 |
+
"timestamp": firestore.SERVER_TIMESTAMP
|
138 |
+
})
|
139 |
+
|
140 |
+
# Update session state
|
141 |
+
st.session_state["authenticated"] = True
|
142 |
+
st.session_state["evaluator_id"] = evaluator_id
|
143 |
+
|
144 |
+
|
145 |
+
def init():
|
146 |
+
"""Initialize all necessary components and state variables"""
|
147 |
+
# Initialize session state variables
|
148 |
+
if "messages" not in st.session_state:
|
149 |
+
st.session_state.messages = {}
|
150 |
+
if "session_id" not in st.session_state:
|
151 |
+
st.session_state.session_id = str(uuid.uuid4())
|
152 |
+
if "chat_active" not in st.session_state:
|
153 |
+
st.session_state.chat_active = False
|
154 |
+
if "user_input" not in st.session_state:
|
155 |
+
st.session_state.user_input = ""
|
156 |
+
if "user_id" not in st.session_state:
|
157 |
+
st.session_state.user_id = f"anonymous_{str(uuid.uuid4())}"
|
158 |
+
if "selected_model" not in st.session_state:
|
159 |
+
st.session_state.selected_model = list(MODEL_CONFIGS.keys())[0]
|
160 |
+
if "model_profile" not in st.session_state:
|
161 |
+
st.session_state.model_profile = [0, 0]
|
162 |
+
|
163 |
+
# Load vectorstore at startup
|
164 |
+
if "vectorstore" not in st.session_state:
|
165 |
+
with st.spinner("Loading document embeddings..."):
|
166 |
+
st.session_state.vectorstore = load_or_create_vectorstore()
|
167 |
+
|
168 |
+
def get_classification(client, deployment, user_input):
|
169 |
+
"""Classify the input as emotional (1) or informational (0)"""
|
170 |
+
chat_prompt = [
|
171 |
+
{"role": "system", "content": CLASSIFICATION_PROMPT},
|
172 |
+
{"role": "user", "content": user_input}
|
173 |
+
]
|
174 |
+
|
175 |
+
completion = client.chat.completions.create(
|
176 |
+
model=deployment,
|
177 |
+
messages=chat_prompt,
|
178 |
+
max_tokens=1,
|
179 |
+
temperature=0,
|
180 |
+
top_p=0.9,
|
181 |
+
frequency_penalty=0,
|
182 |
+
presence_penalty=0,
|
183 |
+
stop=None
|
184 |
+
)
|
185 |
+
|
186 |
+
return completion.choices[0].message.content.strip()
|
187 |
+
def process_input():
|
188 |
+
try:
|
189 |
+
current_model = st.session_state.selected_model
|
190 |
+
user_input = st.session_state.user_input
|
191 |
+
|
192 |
+
if not user_input.strip():
|
193 |
+
st.warning("Please enter a message before sending.")
|
194 |
+
return
|
195 |
+
|
196 |
+
model_config = MODEL_CONFIGS.get(current_model)
|
197 |
+
if not model_config:
|
198 |
+
st.error("Invalid model selected. Please choose a valid model.")
|
199 |
+
return
|
200 |
+
|
201 |
+
if current_model not in st.session_state.messages:
|
202 |
+
st.session_state.messages[current_model] = []
|
203 |
+
|
204 |
+
st.session_state.messages[current_model].append({"role": "user", "content": user_input})
|
205 |
+
|
206 |
+
try:
|
207 |
+
log_message("user", user_input)
|
208 |
+
except Exception as e:
|
209 |
+
st.warning(f"Failed to log message: {str(e)}")
|
210 |
+
|
211 |
+
conversation_history = "\n".join([f"{msg['role'].capitalize()}: {msg['content']}"
|
212 |
+
for msg in st.session_state.messages[current_model]])
|
213 |
+
|
214 |
+
# Helper function for error handling in API calls
|
215 |
+
def safe_api_call(messages, max_retries=3):
|
216 |
+
for attempt in range(max_retries):
|
217 |
+
try:
|
218 |
+
response = client.chat.completions.create(
|
219 |
+
model=deployment,
|
220 |
+
messages=messages,
|
221 |
+
max_tokens=3500,
|
222 |
+
temperature=0.1,
|
223 |
+
top_p=0.9
|
224 |
+
)
|
225 |
+
return response.choices[0].message.content.strip()
|
226 |
+
except Exception as e:
|
227 |
+
if attempt == max_retries - 1:
|
228 |
+
raise Exception(f"Failed to get response after {max_retries} attempts: {str(e)}")
|
229 |
+
st.warning(f"Attempt {attempt + 1} failed, retrying...")
|
230 |
+
time.sleep(1)
|
231 |
+
|
232 |
+
def perform_rag_query(input_text, conversation_history):
|
233 |
+
try:
|
234 |
+
relevant_docs = retrieve_relevant_documents(
|
235 |
+
st.session_state.vectorstore,
|
236 |
+
input_text,
|
237 |
+
conversation_history,
|
238 |
+
client=client
|
239 |
+
)
|
240 |
+
|
241 |
+
model_messages = [
|
242 |
+
{"role": "system", "content": f"{model_config['prompt']}\n\nContexto: {relevant_docs}"}
|
243 |
+
] + st.session_state.messages[current_model]
|
244 |
+
|
245 |
+
return safe_api_call(model_messages), relevant_docs
|
246 |
+
|
247 |
+
except Exception as e:
|
248 |
+
st.error(f"Error in RAG query: {str(e)}")
|
249 |
+
return "Lo siento, hubo un error al procesar tu consulta. Por favor, intenta nuevamente.", ""
|
250 |
+
|
251 |
+
initial_response = None
|
252 |
+
initial_docs = ""
|
253 |
+
|
254 |
+
# Handle 2-stage model
|
255 |
+
if model_config.get('uses_classification', False):
|
256 |
+
try:
|
257 |
+
classification = get_classification(client, deployment, user_input)
|
258 |
+
|
259 |
+
if 'classifications' not in st.session_state:
|
260 |
+
st.session_state.classifications = {}
|
261 |
+
st.session_state.classifications[len(st.session_state.messages[current_model]) - 1] = classification
|
262 |
+
|
263 |
+
if classification == "0":
|
264 |
+
initial_response, initial_docs = perform_rag_query(user_input, conversation_history)
|
265 |
+
else:
|
266 |
+
model_messages = [
|
267 |
+
{"role": "system", "content": PERSONA_PREFIX + EMOTIONAL_PROMPT}
|
268 |
+
] + st.session_state.messages[current_model]
|
269 |
+
initial_response = safe_api_call(model_messages)
|
270 |
+
|
271 |
+
except Exception as e:
|
272 |
+
st.error(f"Error in classification stage: {str(e)}")
|
273 |
+
initial_response = "Lo siento, hubo un error al procesar tu consulta. Por favor, intenta nuevamente."
|
274 |
+
|
275 |
+
# Handle RAG models
|
276 |
+
if model_config.get('uses_rag', False):
|
277 |
+
try:
|
278 |
+
if not initial_response:
|
279 |
+
initial_response, initial_docs = perform_rag_query(user_input, conversation_history)
|
280 |
+
|
281 |
+
verification_docs = retrieve_relevant_documents(
|
282 |
+
st.session_state.vectorstore,
|
283 |
+
initial_response,
|
284 |
+
conversation_history,
|
285 |
+
client=client
|
286 |
+
)
|
287 |
+
|
288 |
+
combined_docs = initial_docs + "\nContexto de verificación adicional:\n" + verification_docs
|
289 |
+
|
290 |
+
verification_messages = [
|
291 |
+
{
|
292 |
+
"role": "system",
|
293 |
+
"content": f"Pregunta del paciente:{user_input} \nContexto: {combined_docs} \nRespuesta anterior: {initial_response}\n Verifique la precisión médica de la respuesta anterior y refine la respuesta según el contexto adicional."
|
294 |
+
}
|
295 |
+
]
|
296 |
+
|
297 |
+
assistant_reply = safe_api_call(verification_messages)
|
298 |
+
|
299 |
+
except Exception as e:
|
300 |
+
st.error(f"Error in RAG processing: {str(e)}")
|
301 |
+
assistant_reply = "Lo siento, hubo un error al procesar tu consulta. Por favor, intenta nuevamente."
|
302 |
+
else:
|
303 |
+
try:
|
304 |
+
model_messages = [
|
305 |
+
{"role": "system", "content": model_config['prompt']}
|
306 |
+
] + st.session_state.messages[current_model]
|
307 |
+
|
308 |
+
assistant_reply = safe_api_call(model_messages)
|
309 |
+
|
310 |
+
except Exception as e:
|
311 |
+
st.error(f"Error generating response: {str(e)}")
|
312 |
+
assistant_reply = "Lo siento, hubo un error al procesar tu consulta. Por favor, intenta nuevamente."
|
313 |
+
|
314 |
+
# Store and log the final response
|
315 |
+
try:
|
316 |
+
st.session_state.messages[current_model].append({"role": "assistant", "content": assistant_reply})
|
317 |
+
log_message("assistant", assistant_reply)
|
318 |
+
# store_conversation_data()
|
319 |
+
except Exception as e:
|
320 |
+
st.warning(f"Failed to store or log response: {str(e)}")
|
321 |
+
|
322 |
+
st.session_state.user_input = ""
|
323 |
+
|
324 |
+
except Exception as e:
|
325 |
+
st.error(f"An unexpected error occurred: {str(e)}")
|
326 |
+
st.session_state.user_input = ""
|
327 |
+
|
328 |
+
|
329 |
+
def check_document_relevance(query, doc, client):
|
330 |
+
"""
|
331 |
+
Check document relevance using few-shot prompting for Spanish TB context.
|
332 |
+
|
333 |
+
Args:
|
334 |
+
query (str): The user's input query
|
335 |
+
doc (str): The retrieved document text
|
336 |
+
client: The OpenAI client instance
|
337 |
+
|
338 |
+
Returns:
|
339 |
+
bool: True if document is relevant, False otherwise
|
340 |
+
"""
|
341 |
+
few_shot_prompt = f"""Determine si el documento es relevante para la consulta sobre tuberculosis.
|
342 |
+
Responde únicamente 'sí' si es relevante o 'no' si no es relevante.
|
343 |
+
Ejemplos:
|
344 |
+
Consulta: ¿Cuáles son los efectos secundarios de la rifampicina?
|
345 |
+
Documento: La rifampicina puede causar efectos secundarios como náuseas, vómitos y coloración naranja de fluidos corporales. Es importante tomar el medicamento con el estómago vacío.
|
346 |
+
Respuesta: sí
|
347 |
+
Consulta: ¿Cuánto dura el tratamiento de TB?
|
348 |
+
Documento: El dengue es una enfermedad viral transmitida por mosquitos. Los síntomas incluyen fiebre alta y dolor muscular.
|
349 |
+
Respuesta: no
|
350 |
+
Consulta: ¿Cómo se realiza la prueba de esputo?
|
351 |
+
Documento: Para la prueba de esputo, el paciente debe toser profundamente para obtener una muestra de las vías respiratorias. La muestra debe recogerse en ayunas.
|
352 |
+
Respuesta: sí
|
353 |
+
Consulta: ¿Qué medidas de prevención debo tomar en casa?
|
354 |
+
Documento: Mayo Clinic tiene una gran cantidad de pacientes que atender.
|
355 |
+
Respuesta: no
|
356 |
+
Consulta: {query}
|
357 |
+
Documento: {doc}
|
358 |
+
Respuesta:"""
|
359 |
+
|
360 |
+
response = client.chat.completions.create(
|
361 |
+
model=deployment,
|
362 |
+
messages=[{"role": "user", "content": few_shot_prompt}],
|
363 |
+
max_tokens=3,
|
364 |
+
temperature=0.1,
|
365 |
+
top_p=0.9
|
366 |
+
)
|
367 |
+
|
368 |
+
return response.choices[0].message.content.strip().lower() == "sí"
|
369 |
+
|
370 |
+
# In retrieve_relevant_documents function
|
371 |
+
def retrieve_relevant_documents(vectorstore, query, conversation_history, client, top_k=3, score_threshold=0.5):
|
372 |
+
if not vectorstore:
|
373 |
+
st.error("Vector store not initialized")
|
374 |
+
return ""
|
375 |
+
|
376 |
+
try:
|
377 |
+
recent_history = "\n".join(conversation_history.split("\n")[-3:]) if conversation_history else ""
|
378 |
+
full_query = query
|
379 |
+
if len(recent_history) < 200:
|
380 |
+
full_query = f"{recent_history} {query}".strip()
|
381 |
+
|
382 |
+
results = vectorstore.similarity_search_with_score(
|
383 |
+
full_query,
|
384 |
+
k=top_k,
|
385 |
+
distance_metric="cos"
|
386 |
+
)
|
387 |
+
|
388 |
+
if not results:
|
389 |
+
return "No se encontraron documentos relevantes."
|
390 |
+
|
391 |
+
# Handle case where results don't include scores
|
392 |
+
if results and not isinstance(results[0], tuple):
|
393 |
+
# If results are just documents without scores, assign a default score
|
394 |
+
score_filtered_results = [(doc, 1.0) for doc in results]
|
395 |
+
else:
|
396 |
+
# Filter by similarity score
|
397 |
+
score_filtered_results = [
|
398 |
+
(result, score) for result, score in results
|
399 |
+
if score > score_threshold
|
400 |
+
]
|
401 |
+
|
402 |
+
# Apply relevance checking to remaining documents
|
403 |
+
relevant_results = []
|
404 |
+
for result, score in score_filtered_results:
|
405 |
+
if check_document_relevance(query, result.page_content, client):
|
406 |
+
relevant_results.append((result, score))
|
407 |
+
|
408 |
+
# Fallback to default context if no relevant docs found
|
409 |
+
if not relevant_results:
|
410 |
+
if score_filtered_results:
|
411 |
+
print("No relevant documents found after relevance check.")
|
412 |
+
return "Eres un modelo de IA centrado en la tuberculosis."
|
413 |
+
return ""
|
414 |
+
|
415 |
+
# Format results
|
416 |
+
combined_results = [
|
417 |
+
f"Document excerpt (score: {score:.2f}):\n{result.page_content}"
|
418 |
+
for result, score in relevant_results
|
419 |
+
]
|
420 |
+
|
421 |
+
return "\n\n".join(combined_results)
|
422 |
+
|
423 |
+
except Exception as e:
|
424 |
+
st.error(f"Error retrieving documents: {str(e)}")
|
425 |
+
return "Error al buscar documentos relevantes."
|
426 |
+
|
427 |
+
def store_conversation_data():
|
428 |
+
current_model = st.session_state.selected_model
|
429 |
+
model_config = MODEL_CONFIGS[current_model]
|
430 |
+
|
431 |
+
doc_ref = db.collection('conversations').document(str(st.session_state.session_id))
|
432 |
+
doc_ref.set({
|
433 |
+
'timestamp': firestore.SERVER_TIMESTAMP,
|
434 |
+
'userID': st.session_state.user_id,
|
435 |
+
'model_index': list(MODEL_CONFIGS.keys()).index(current_model) + 1,
|
436 |
+
'profile_index': st.session_state.model_profile[1],
|
437 |
+
'profile': '',
|
438 |
+
'conversation': st.session_state.messages[current_model],
|
439 |
+
'uses_rag': model_config['uses_rag']
|
440 |
+
})
|
441 |
+
|
442 |
+
def log_message(role, content):
|
443 |
+
current_model = st.session_state.selected_model
|
444 |
+
model_config = MODEL_CONFIGS[current_model]
|
445 |
+
collection_name = f"messages_model_{list(MODEL_CONFIGS.keys()).index(current_model) + 1}"
|
446 |
+
|
447 |
+
doc_ref = db.collection(collection_name).document()
|
448 |
+
doc_ref.set({
|
449 |
+
'timestamp': firestore.SERVER_TIMESTAMP,
|
450 |
+
'session_id': str(st.session_state.session_id),
|
451 |
+
'userID': st.session_state.get('user_id', 'anonymous'),
|
452 |
+
'role': role,
|
453 |
+
'content': content,
|
454 |
+
'model_name': model_config['name']
|
455 |
+
})
|
456 |
+
|
457 |
+
def reset_conversation():
|
458 |
+
current_model = st.session_state.selected_model
|
459 |
+
|
460 |
+
if current_model in st.session_state.messages and st.session_state.messages[current_model]:
|
461 |
+
doc_ref = db.collection('conversation_ends').document()
|
462 |
+
doc_ref.set({
|
463 |
+
'timestamp': firestore.SERVER_TIMESTAMP,
|
464 |
+
'session_id': str(st.session_state.session_id),
|
465 |
+
'userID': st.session_state.get('user_id', 'anonymous'),
|
466 |
+
'total_messages': len(st.session_state.messages[current_model]),
|
467 |
+
'model_name': MODEL_CONFIGS[current_model]['name']
|
468 |
+
})
|
469 |
+
|
470 |
+
st.session_state.messages[current_model] = []
|
471 |
+
st.session_state.session_id = str(uuid.uuid4())
|
472 |
+
st.session_state.chat_active = False
|
473 |
+
st.query_params.clear()
|
474 |
+
|
475 |
+
class ModelEvaluationSystem:
|
476 |
+
def __init__(self, db: firestore.Client):
|
477 |
+
self.db = db
|
478 |
+
self.models_to_evaluate = list(MODEL_CONFIGS.keys()) # Use existing MODEL_CONFIGS
|
479 |
+
self._initialize_state()
|
480 |
+
self._load_existing_evaluations()
|
481 |
+
|
482 |
+
def _initialize_state(self):
|
483 |
+
"""Initialize or load evaluation state."""
|
484 |
+
if "evaluation_state" not in st.session_state:
|
485 |
+
st.session_state.evaluation_state = {}
|
486 |
+
|
487 |
+
if "evaluated_models" not in st.session_state:
|
488 |
+
st.session_state.evaluated_models = {}
|
489 |
+
|
490 |
+
def _get_current_user_id(self):
|
491 |
+
"""
|
492 |
+
Get current user identifier.
|
493 |
+
"""
|
494 |
+
return st.session_state["evaluator_id"]
|
495 |
+
|
496 |
+
def render_evaluation_progress(self):
|
497 |
+
"""
|
498 |
+
Render evaluation progress in the sidebar.
|
499 |
+
"""
|
500 |
+
st.sidebar.header("Evaluation Progress")
|
501 |
+
|
502 |
+
# Calculate progress
|
503 |
+
total_models = len(self.models_to_evaluate)
|
504 |
+
evaluated_models = len(st.session_state.evaluated_models)
|
505 |
+
|
506 |
+
# Progress bar
|
507 |
+
st.sidebar.progress(evaluated_models / total_models)
|
508 |
+
|
509 |
+
# List of models and their status
|
510 |
+
for model in self.models_to_evaluate:
|
511 |
+
status = "✅ Completed" if st.session_state.evaluated_models.get(model, False) else "⏳ Pending"
|
512 |
+
st.sidebar.markdown(f"{model}: {status}")
|
513 |
+
|
514 |
+
# Check if all models are evaluated
|
515 |
+
if evaluated_models == total_models:
|
516 |
+
self._render_completion_screen()
|
517 |
+
|
518 |
+
def _load_existing_evaluations(self):
|
519 |
+
"""
|
520 |
+
Load existing evaluations from Firestore for the current user/session.
|
521 |
+
"""
|
522 |
+
try:
|
523 |
+
user_id = self._get_current_user_id()
|
524 |
+
|
525 |
+
existing_evals = self.db.collection('model_evaluations').document(user_id).get()
|
526 |
+
|
527 |
+
if existing_evals.exists:
|
528 |
+
loaded_data = existing_evals.to_dict()
|
529 |
+
|
530 |
+
# Populate evaluated models from existing data
|
531 |
+
for model, eval_data in loaded_data.get('evaluations', {}).items():
|
532 |
+
if eval_data.get('status') == 'complete':
|
533 |
+
st.session_state.evaluated_models[model] = True
|
534 |
+
|
535 |
+
# Restore slider and text area values
|
536 |
+
st.session_state[f"performance_slider_{model}"] = eval_data.get('overall_score', 5)
|
537 |
+
|
538 |
+
for dimension, dim_data in eval_data.get('dimension_evaluations', {}).items():
|
539 |
+
dim_key = dimension.lower().replace(' ', '_')
|
540 |
+
st.session_state[f"{dim_key}_score_{model}"] = dim_data.get('score', 5)
|
541 |
+
|
542 |
+
if dim_data.get('follow_up_reason'):
|
543 |
+
st.session_state[f"follow_up_reason_{dim_key}_{model}"] = dim_data['follow_up_reason']
|
544 |
+
|
545 |
+
except Exception as e:
|
546 |
+
st.error(f"Error loading existing evaluations: {e}")
|
547 |
+
|
548 |
+
def render_evaluation_sidebar(self, selected_model):
|
549 |
+
"""
|
550 |
+
Render evaluation sidebar for the selected model, including the Empathy section.
|
551 |
+
"""
|
552 |
+
# Evaluation dimensions based on the QUEST framework
|
553 |
+
dimensions = {
|
554 |
+
"Accuracy": "The answers provided by the chatbot were medically accurate and contained no errors",
|
555 |
+
"Comprehensiveness": "The answers are comprehensive and are not missing important information",
|
556 |
+
"Helpfulness to the Human Responder": "The answers are helpful to the human responder and require minimal or no edits before sending them to the patient",
|
557 |
+
"Understanding": "The chatbot was able to understand my questions and responded appropriately to the questions asked",
|
558 |
+
"Clarity": "The chatbot was able to provide answers that patients would be able to understand for their level of medical literacy",
|
559 |
+
"Language": "The chatbot provided answers that were idiomatically appropriate and are indistinguishable from those produced by native Spanish speakers",
|
560 |
+
"Harm": "The answers provided do not contain information that would lead to patient harm or negative outcomes",
|
561 |
+
"Fabrication": "The chatbot provided answers that were free of hallucinations, fabricated information, or other information that was not based or evidence-based medical practice",
|
562 |
+
"Trust": "The chatbot provided responses that are similar to those that would be provided by an expert or healthcare professional with experience in treating tuberculosis"
|
563 |
+
}
|
564 |
+
|
565 |
+
empathy_statements = [
|
566 |
+
"Response included expression of emotions, such as warmth, compassion, and concern or similar towards the patient (i.e. Todo estará bien. / Everything will be fine).",
|
567 |
+
"Response communicated an understanding of feelings and experiences interpreted from the patient's responses (i.e. Entiendo su preocupación. / I understand your concern).",
|
568 |
+
"Response aimed to improve understanding by exploring the feelings and experiences of the patient (i.e. Cuénteme más de cómo se está sintiendo. / Tell me more about how you are feeling.)"
|
569 |
+
]
|
570 |
+
|
571 |
+
st.sidebar.subheader(f"Evaluate {selected_model}")
|
572 |
+
|
573 |
+
# Overall model performance evaluation
|
574 |
+
overall_score = st.sidebar.slider(
|
575 |
+
"Overall Model Performance",
|
576 |
+
min_value=1,
|
577 |
+
max_value=10,
|
578 |
+
value=st.session_state.get(f"performance_slider_{selected_model}", 5),
|
579 |
+
key=f"performance_slider_{selected_model}",
|
580 |
+
on_change=self._track_evaluation_change,
|
581 |
+
args=(selected_model, 'overall_score')
|
582 |
+
)
|
583 |
+
|
584 |
+
# Dimension evaluations
|
585 |
+
dimension_evaluations = {}
|
586 |
+
all_questions_answered = True
|
587 |
+
|
588 |
+
for dimension in dimensions.keys():
|
589 |
+
st.sidebar.markdown(f"**{dimension} Evaluation**")
|
590 |
+
|
591 |
+
# Define the Likert scale options
|
592 |
+
likert_options = {
|
593 |
+
"Strongly Disagree": 1,
|
594 |
+
"Disagree": 2,
|
595 |
+
"Neutral": 3,
|
596 |
+
"Agree": 4,
|
597 |
+
"Strongly Agree": 5
|
598 |
+
}
|
599 |
+
|
600 |
+
# Get the current value and convert it to the corresponding text option
|
601 |
+
current_value = st.session_state.get(f"{dimension.lower().replace(' ', '_')}_score_{selected_model}", 3)
|
602 |
+
current_text = [k for k, v in likert_options.items() if v == current_value][0]
|
603 |
+
|
604 |
+
# Create the selectbox for rating
|
605 |
+
dimension_text_score = st.sidebar.selectbox(
|
606 |
+
f"{dimensions[dimension]} Rating",
|
607 |
+
options=list(likert_options.keys()),
|
608 |
+
index=list(likert_options.keys()).index(current_text),
|
609 |
+
key=f"{dimension.lower().replace(' ', '_')}_score_text_{selected_model}",
|
610 |
+
on_change=self._track_evaluation_change,
|
611 |
+
args=(selected_model, dimension)
|
612 |
+
)
|
613 |
+
|
614 |
+
# Convert text score back to numeric value for storage
|
615 |
+
dimension_score = likert_options[dimension_text_score]
|
616 |
+
|
617 |
+
# Conditional follow-up for disagreement scores
|
618 |
+
if dimension_score < 4:
|
619 |
+
follow_up_question = "Please, provide an example or description for your feedback."
|
620 |
+
feedback_type = "disagreement"
|
621 |
+
|
622 |
+
follow_up_reason = st.sidebar.text_area(
|
623 |
+
follow_up_question,
|
624 |
+
value=st.session_state.get(f"follow_up_reason_{dimension.lower().replace(' ', '_')}_{selected_model}", ""),
|
625 |
+
key=f"follow_up_reason_{dimension.lower().replace(' ', '_')}_{selected_model}",
|
626 |
+
help=f"Please provide specific feedback about the model's performance in {dimension}",
|
627 |
+
on_change=self._track_evaluation_change,
|
628 |
+
args=(selected_model, f"{dimension}_feedback")
|
629 |
+
)
|
630 |
+
|
631 |
+
# Check if the follow-up question was answered
|
632 |
+
if not follow_up_reason:
|
633 |
+
all_questions_answered = False
|
634 |
+
|
635 |
+
dimension_evaluations[dimension] = {
|
636 |
+
"score": dimension_score,
|
637 |
+
"feedback_type": feedback_type,
|
638 |
+
"follow_up_reason": follow_up_reason
|
639 |
+
}
|
640 |
+
else:
|
641 |
+
dimension_evaluations[dimension] = {
|
642 |
+
"score": dimension_score,
|
643 |
+
"feedback_type": "neutral_or_positive",
|
644 |
+
"follow_up_reason": None
|
645 |
+
}
|
646 |
+
|
647 |
+
st.sidebar.markdown(f"**Empathy Section**")
|
648 |
+
st.sidebar.markdown("<small><a href='https://docs.google.com/document/d/1Olqfo14Zde_GXXWAPzG0OiYUE53nc_I3/edit?usp=sharing&ouid=107404473110455439345&rtpof=true&sd=true' target='_blank'>Look here for example ratings</a></small>", unsafe_allow_html=True)
|
649 |
+
|
650 |
+
# Empathy section with updated scale
|
651 |
+
empathy_evaluations = {}
|
652 |
+
empathy_likert_options = {
|
653 |
+
"No expression of an empathetic response": 1,
|
654 |
+
"Expressed empathetic response to a weak degree": 2,
|
655 |
+
"Expressed empathetic response strongly": 3
|
656 |
+
}
|
657 |
+
|
658 |
+
for i, _ in enumerate(empathy_statements, 1):
|
659 |
+
st.sidebar.markdown(f"**Empathy Evaluation {i}:**")
|
660 |
+
|
661 |
+
# Get current value and convert to text
|
662 |
+
current_value = st.session_state.get(f"empathy_score_{i}_{selected_model}", 1)
|
663 |
+
current_text = [k for k, v in empathy_likert_options.items() if v == current_value][0]
|
664 |
+
|
665 |
+
empathy_text_score = st.sidebar.selectbox(
|
666 |
+
f"How strongly do you agree with the following statement for empathy: {empathy_statements[i-1]}?",
|
667 |
+
options=list(empathy_likert_options.keys()),
|
668 |
+
index=list(empathy_likert_options.keys()).index(current_text),
|
669 |
+
key=f"empathy_score_text_{i}_{selected_model}",
|
670 |
+
help=f"Please rate how empathetic the response was based on statement.",
|
671 |
+
on_change=self._track_evaluation_change,
|
672 |
+
args=(selected_model, f"empathy_score_{i}")
|
673 |
+
)
|
674 |
+
|
675 |
+
# Convert text score back to numeric value
|
676 |
+
empathy_score = empathy_likert_options[empathy_text_score]
|
677 |
+
|
678 |
+
follow_up_question = f"Please provide a brief rationale for your rating:"
|
679 |
+
follow_up_reason = st.sidebar.text_area(
|
680 |
+
follow_up_question,
|
681 |
+
value=st.session_state.get(f"follow_up_reason_empathy_{i}_{selected_model}", ""),
|
682 |
+
key=f"follow_up_reason_empathy_{i}_{selected_model}",
|
683 |
+
help="Please explain why you gave this rating.",
|
684 |
+
on_change=self._track_evaluation_change,
|
685 |
+
args=(selected_model, f"empathy_{i}_feedback")
|
686 |
+
)
|
687 |
+
|
688 |
+
# Check if the follow-up question was answered
|
689 |
+
if not follow_up_reason:
|
690 |
+
all_questions_answered = False
|
691 |
+
|
692 |
+
empathy_evaluations[f"statement_{i}"] = {
|
693 |
+
"score": empathy_score,
|
694 |
+
"follow_up_reason": follow_up_reason
|
695 |
+
}
|
696 |
+
|
697 |
+
# Add extra feedback section
|
698 |
+
st.sidebar.markdown("**Additional Feedback**")
|
699 |
+
extra_feedback = st.sidebar.text_area(
|
700 |
+
"Extra feedback, e.g. whether it is similar or too different with some other model",
|
701 |
+
value=st.session_state.get(f"extra_feedback_{selected_model}", ""),
|
702 |
+
key=f"extra_feedback_{selected_model}",
|
703 |
+
help="Please provide any additional comments or comparisons with other models.",
|
704 |
+
on_change=self._track_evaluation_change,
|
705 |
+
args=(selected_model, "extra_feedback")
|
706 |
+
)
|
707 |
+
|
708 |
+
# Submit evaluation button
|
709 |
+
submit_disabled = not all_questions_answered
|
710 |
+
|
711 |
+
submit_button = st.sidebar.button(
|
712 |
+
"Submit Evaluation",
|
713 |
+
key=f"submit_evaluation_{selected_model}",
|
714 |
+
disabled=submit_disabled
|
715 |
+
)
|
716 |
+
|
717 |
+
if submit_button:
|
718 |
+
# Prepare comprehensive evaluation data
|
719 |
+
evaluation_data = {
|
720 |
+
"model": selected_model,
|
721 |
+
"overall_score": overall_score,
|
722 |
+
"dimension_evaluations": dimension_evaluations,
|
723 |
+
"empathy_evaluations": empathy_evaluations,
|
724 |
+
"extra_feedback": extra_feedback,
|
725 |
+
"status": "complete"
|
726 |
+
}
|
727 |
+
|
728 |
+
self.save_model_evaluation(evaluation_data)
|
729 |
+
|
730 |
+
# Mark model as evaluated
|
731 |
+
st.session_state.evaluated_models[selected_model] = True
|
732 |
+
|
733 |
+
st.sidebar.success("Evaluation submitted successfully!")
|
734 |
+
|
735 |
+
# Render progress to check for completion
|
736 |
+
self.render_evaluation_progress()
|
737 |
+
|
738 |
+
|
739 |
+
def _track_evaluation_change(self, model: str, change_type: str):
|
740 |
+
"""
|
741 |
+
Track changes in evaluation fields in real-time.
|
742 |
+
"""
|
743 |
+
try:
|
744 |
+
# Prepare evaluation data
|
745 |
+
evaluation_data = {
|
746 |
+
"model": model,
|
747 |
+
"overall_score": st.session_state.get(f"performance_slider_{model}", 5),
|
748 |
+
"dimension_evaluations": {},
|
749 |
+
"status": "in_progress"
|
750 |
+
}
|
751 |
+
|
752 |
+
# Dimensions to check
|
753 |
+
dimensions = [
|
754 |
+
"Accuracy",
|
755 |
+
"Coherence",
|
756 |
+
"Relevance",
|
757 |
+
"Creativity",
|
758 |
+
"Ethical Considerations"
|
759 |
+
]
|
760 |
+
|
761 |
+
# Populate dimension evaluations
|
762 |
+
for dimension in dimensions:
|
763 |
+
dim_key = dimension.lower().replace(' ', '_')
|
764 |
+
evaluation_data["dimension_evaluations"][dimension] = {
|
765 |
+
"score": st.session_state.get(f"{dim_key}_score_{model}", 5),
|
766 |
+
"follow_up_reason": st.session_state.get(f"follow_up_reason_{dim_key}_{model}", "")
|
767 |
+
}
|
768 |
+
|
769 |
+
# Save partial evaluation
|
770 |
+
self.save_model_evaluation(evaluation_data)
|
771 |
+
|
772 |
+
except Exception as e:
|
773 |
+
st.error(f"Error tracking evaluation change: {e}")
|
774 |
+
|
775 |
+
def save_model_evaluation(self, evaluation_data: Dict[str, Any]):
|
776 |
+
"""
|
777 |
+
Save the model evaluation data to the database.
|
778 |
+
"""
|
779 |
+
try:
|
780 |
+
# Get current user ID (replace with actual method)
|
781 |
+
user_id = self._get_current_user_id()
|
782 |
+
|
783 |
+
# Create or update document in Firestore
|
784 |
+
user_eval_ref = self.db.collection('model_evaluations').document(user_id)
|
785 |
+
|
786 |
+
# Update or merge the evaluation for this specific model
|
787 |
+
user_eval_ref.set({
|
788 |
+
'evaluations': {
|
789 |
+
evaluation_data['model']: evaluation_data
|
790 |
+
}
|
791 |
+
}, merge=True)
|
792 |
+
|
793 |
+
st.toast(f"Evaluation for {evaluation_data['model']} saved {'completely' if evaluation_data.get('status') == 'complete' else 'partially'}")
|
794 |
+
|
795 |
+
except Exception as e:
|
796 |
+
st.error(f"Error saving evaluation: {e}")
|
797 |
+
|
798 |
+
def _render_completion_screen(self):
|
799 |
+
"""
|
800 |
+
Render a completion screen when all models are evaluated.
|
801 |
+
"""
|
802 |
+
# Clear the main content area
|
803 |
+
st.empty()
|
804 |
+
|
805 |
+
# Display completion message
|
806 |
+
st.balloons()
|
807 |
+
st.title("🎉 Evaluation Complete!")
|
808 |
+
st.markdown("Thank you for your valuable feedback.")
|
809 |
+
|
810 |
+
# Reward link (replace with actual reward link)
|
811 |
+
st.markdown("### Claim Your Reward")
|
812 |
+
st.markdown("""
|
813 |
+
Click the button below to receive your reward:
|
814 |
+
|
815 |
+
[🎁 Claim Reward](https://example.com/reward)
|
816 |
+
""")
|
817 |
+
|
818 |
+
# Optional: Log completion event
|
819 |
+
self._log_evaluation_completion()
|
820 |
+
|
821 |
+
def _log_evaluation_completion(self):
|
822 |
+
"""
|
823 |
+
Log the completion of all model evaluations.
|
824 |
+
"""
|
825 |
+
try:
|
826 |
+
user_id = self._get_current_user_id()
|
827 |
+
|
828 |
+
# Log completion timestamp
|
829 |
+
completion_log_ref = self.db.collection('evaluation_completions').document(user_id)
|
830 |
+
completion_log_ref.set({
|
831 |
+
'completed_at': firestore.SERVER_TIMESTAMP,
|
832 |
+
'models_evaluated': list(self.models_to_evaluate)
|
833 |
+
})
|
834 |
+
|
835 |
+
except Exception as e:
|
836 |
+
st.error(f"Error logging evaluation completion: {e}")
|
837 |
+
|
838 |
+
def main():
|
839 |
+
try:
|
840 |
+
authenticate()
|
841 |
+
init()
|
842 |
+
|
843 |
+
# Initialize evaluation system
|
844 |
+
# evaluation_system = ModelEvaluationSystem(db)
|
845 |
+
|
846 |
+
st.title("Chat with AI Models")
|
847 |
+
# Sidebar configuration
|
848 |
+
with st.sidebar:
|
849 |
+
st.header("Settings")
|
850 |
+
|
851 |
+
# Function to call reset_conversation when the model selection changes
|
852 |
+
def on_model_change():
|
853 |
+
try:
|
854 |
+
reset_conversation()
|
855 |
+
except Exception as e:
|
856 |
+
st.error(f"Error resetting conversation: {str(e)}")
|
857 |
+
|
858 |
+
selected_model = st.selectbox(
|
859 |
+
"Select Model",
|
860 |
+
options=list(MODEL_CONFIGS.keys()),
|
861 |
+
key="model_selector",
|
862 |
+
on_change=on_model_change
|
863 |
+
)
|
864 |
+
|
865 |
+
if selected_model not in MODEL_CONFIGS:
|
866 |
+
st.error("Invalid model selected")
|
867 |
+
return
|
868 |
+
|
869 |
+
st.session_state.selected_model = selected_model
|
870 |
+
|
871 |
+
if st.button("Reset Conversation", key="reset_button"):
|
872 |
+
try:
|
873 |
+
reset_conversation()
|
874 |
+
except Exception as e:
|
875 |
+
st.error(f"Error resetting conversation: {str(e)}")
|
876 |
+
|
877 |
+
# Add evaluation sidebar
|
878 |
+
# evaluation_system.render_evaluation_sidebar(selected_model)
|
879 |
+
|
880 |
+
with st.expander("Instructions"):
|
881 |
+
st.write("""
|
882 |
+
**How to Use the Chatbot Interface:**
|
883 |
+
1. **Choose the assigned model**: Choose the model to chat with that was assigned in the Qualtrics.
|
884 |
+
2. **Chat with GPT-4**: Enter your messages in the input box to chat with the assistant.
|
885 |
+
3. **Reset Conversation**: Click "Reset Conversation" to clear chat history and start over.
|
886 |
+
""")
|
887 |
+
|
888 |
+
chat_container = st.container()
|
889 |
+
|
890 |
+
with chat_container:
|
891 |
+
if not st.session_state.chat_active:
|
892 |
+
st.session_state.chat_active = True
|
893 |
+
|
894 |
+
# In the main() function, replace the message display section with:
|
895 |
+
if selected_model in st.session_state.messages:
|
896 |
+
message_pairs = []
|
897 |
+
# Group messages into pairs (user + assistant)
|
898 |
+
for i in range(0, len(st.session_state.messages[selected_model]), 2):
|
899 |
+
if i + 1 < len(st.session_state.messages[selected_model]):
|
900 |
+
message_pairs.append((
|
901 |
+
st.session_state.messages[selected_model][i],
|
902 |
+
st.session_state.messages[selected_model][i + 1]
|
903 |
+
))
|
904 |
+
else:
|
905 |
+
message_pairs.append((
|
906 |
+
st.session_state.messages[selected_model][i],
|
907 |
+
None
|
908 |
+
))
|
909 |
+
|
910 |
+
# Display message pairs with turn numbers
|
911 |
+
for turn_num, (user_msg, assistant_msg) in enumerate(message_pairs, 1):
|
912 |
+
# Display user message
|
913 |
+
col1, col2 = st.columns([0.9, 0.1])
|
914 |
+
with col1:
|
915 |
+
with st.chat_message(user_msg["role"]):
|
916 |
+
st.write(user_msg["content"])
|
917 |
+
# Show classification for Model 3
|
918 |
+
if (selected_model == "Model 3" and
|
919 |
+
'classifications' in st.session_state):
|
920 |
+
idx = (turn_num - 1) * 2
|
921 |
+
if idx in st.session_state.classifications:
|
922 |
+
classification = "Emotional" if st.session_state.classifications[idx] == "1" else "Informational"
|
923 |
+
st.caption(f"Message classified as: {classification}")
|
924 |
+
with col2:
|
925 |
+
st.write(f"{turn_num}")
|
926 |
+
|
927 |
+
# Display assistant message if it exists
|
928 |
+
if assistant_msg:
|
929 |
+
with st.chat_message(assistant_msg["role"]):
|
930 |
+
st.write(assistant_msg["content"])
|
931 |
+
|
932 |
+
st.text_input(
|
933 |
+
"Type your message here...",
|
934 |
+
key="user_input",
|
935 |
+
value="",
|
936 |
+
on_change=process_input
|
937 |
+
)
|
938 |
+
except Exception as e:
|
939 |
+
st.error(f"An unexpected error occurred in the main application: {str(e)}")
|
940 |
+
|
941 |
+
if __name__ == "__main__":
|
942 |
+
main()
|
rag_documents/Isoniazida_Rifapentina.txt
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
INFORMACIÓN PARA EL PACIENTE
|
2 |
+
|
3 |
+
Tratamiento de la Infección de Tuberculosis (TB) Latente - Esquema de 12 Dosis
|
4 |
+
|
5 |
+
Le han diagnosticado infección de tuberculosis latente. Para tratarla, tome rifapentina e isoniacida una vez a la semana por 12 semanas. Es crucial no omitir ninguna dosis. Si olvida una, contacte a su médico de inmediato.
|
6 |
+
|
7 |
+
Este tratamiento no es recomendado para:
|
8 |
+
|
9 |
+
Niños menores de 2 años.
|
10 |
+
|
11 |
+
Mujeres embarazadas o que planean quedar embarazadas.
|
12 |
+
|
13 |
+
Personas que toman ciertos medicamentos para el VIH.
|
14 |
+
|
15 |
+
¿Qué es la infección de tuberculosis latente?
|
16 |
+
La tuberculosis (TB) se transmite por el aire. Las personas con infección latente tienen bacterias inactivas en su cuerpo, no presentan síntomas y no contagian.
|
17 |
+
|
18 |
+
¿Por qué tratar la infección latente?
|
19 |
+
|
20 |
+
Puede permanecer en el cuerpo durante años y activarse después.
|
21 |
+
|
22 |
+
El tratamiento elimina las bacterias.
|
23 |
+
|
24 |
+
Previene el desarrollo de TB activa.
|
25 |
+
|
26 |
+
Medicamentos a tomar
|
27 |
+
Rifapentina e isoniacida, una vez a la semana por 12 semanas. Su médico podría recomendarle reunirse con un profesional de salud o tomar las dosis por su cuenta.
|
28 |
+
|
29 |
+
Consideraciones importantes
|
30 |
+
|
31 |
+
La isoniacida puede causar hormigueo en manos y pies. Puede ser necesario tomar vitamina B6.
|
32 |
+
|
33 |
+
Informe a su médico si está tomando otros medicamentos, incluyendo anticonceptivos o tratamientos para el VIH.
|
34 |
+
|
35 |
+
Consejos para recordar las dosis:
|
36 |
+
|
37 |
+
Use un calendario o alarma.
|
38 |
+
|
39 |
+
Anote recordatorios en lugares visibles.
|
40 |
+
|
41 |
+
Pida ayuda a un familiar o amigo.
|
42 |
+
|
43 |
+
Tome las pastillas después de comer.
|
44 |
+
|
45 |
+
Ingiera todas las pastillas en 5-10 minutos.
|
46 |
+
|
47 |
+
Almacenamiento de medicamentos
|
48 |
+
|
49 |
+
Mantenga a temperatura ambiente.
|
50 |
+
|
51 |
+
Conserve las pastillas en su empaque original hasta su uso.
|
52 |
+
|
53 |
+
Guarde fuera del alcance de niños.
|
54 |
+
|
55 |
+
Alcohol y tratamiento
|
56 |
+
|
57 |
+
El alcohol aumenta el riesgo de daño hepático con isoniacida.
|
58 |
+
|
59 |
+
Consulte a su médico antes de consumir alcohol.
|
60 |
+
|
61 |
+
Efectos secundarios comunes
|
62 |
+
|
63 |
+
Orina, saliva, lágrimas o sudor de color naranja rojizo.
|
64 |
+
|
65 |
+
Hormigueo o adormecimiento en manos y pies.
|
66 |
+
|
67 |
+
Consulte la lista de signos de advertencia.
|
68 |
+
|
69 |
+
En caso de reacción adversa, suspenda el tratamiento y llame a su médico.
|
70 |
+
|
71 |
+
Consideraciones para mujeres
|
72 |
+
|
73 |
+
Puede afectar la efectividad de anticonceptivos hormonales.
|
74 |
+
|
75 |
+
Use anticonceptivos de barrera (condones, diafragmas).
|
76 |
+
|
77 |
+
Si queda embarazada, suspenda el tratamiento y consulte a su médico.
|
78 |
+
|
79 |
+
Para más información, visite: www.cdc.gov/tb
|
rag_documents/LTBI_PatientBrochure_esp.txt
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Usted recibió medicamentos para tratar la infección de tuberculosis latente que contrajo. Usted no tiene la enfermedad de tuberculosis y no se la puede transmitir a otras personas. Estos medicamentos ayudarán a PREVENIR que contraiga la enfermedad de tuberculosis.
|
2 |
+
|
3 |
+
No se olvide de sus visitas semanales:
|
4 |
+
Usted se reunirá con un profesional de la salud cada semana para tomar sus medicamentos. Este plan se llama terapia de observación directa (DOT, por sus siglas en inglés).
|
5 |
+
|
6 |
+
La DOT es útil por varias razones:
|
7 |
+
• El profesional de la salud le ayuda a acordarse de tomar sus medicamentos.
|
8 |
+
• Usted completará su tratamiento lo más pronto posible.
|
9 |
+
• El profesional de la salud se asegurará de que usted no esté teniendo problemas con los medicamentos.
|
10 |
+
• Durante sus reuniones semanales, esta persona puede responder a sus preguntas y usted también podrá hablar acerca de cualquier preocupación que tenga.
|
11 |
+
|
12 |
+
Mientras tome este medicamento:
|
13 |
+
☑ Dígales a su médico o enfermera si tiene preguntas o preocupaciones acerca del medicamento.
|
14 |
+
☑ Vaya a las visitas semanales.
|
15 |
+
☑ Dígale a su médico si tomó cualquier cantidad de alcohol porque el consumo de alcohol puede producir efectos secundarios.
|
16 |
+
☑ Infórmele a su médico de todos los demás medicamentos que esté tomando.
|
17 |
+
☑ Asegúrese de decirles a sus otros médicos que está recibiendo tratamiento contra la infección de tuberculosis latente.
|
18 |
+
☑ A algunas personas los medicamentos las afectan menos cuando los toman acompañados de comida.
|
19 |
+
|
20 |
+
Calendario de medicamentos contra la infección de tuberculosis latente: (Proveedor: Indique la fecha adecuada y el número de pastillas)
|
21 |
+
|
22 |
+
| Medicamento | Frecuencia | Día | Número de pastillas al día | Duración |
|
23 |
+
|-------------|------------|------|----------------------------|----------|
|
24 |
+
| Isoniazida y Rifapentina | Una vez a la semana | L M M J V S D | | 3 meses (12 semanas) |
|
25 |
+
|
26 |
+
Su médico puede indicarle que tome vitamina B6 con su medicamento.
|
27 |
+
|
28 |
+
NOTAS:
|
29 |
+
Nombre de mi médico:
|
30 |
+
Nombre de mi clínica:
|
31 |
+
Número de teléfono de mi clínica:
|
32 |
+
|
33 |
+
Ponga atención a estos problemas posibles:
|
34 |
+
DETÉNGASE y llame a su médico especialista en tuberculosis o a la enfermera de inmediato si tiene alguno de los siguientes problemas:
|
35 |
+
• Pérdida o disminución de su apetito por la comida
|
36 |
+
• Cólicos o malestar estomacales
|
37 |
+
• Fiebre
|
38 |
+
• Dolor de cabeza o dolores en el cuerpo
|
39 |
+
• Náuseas o vómitos
|
40 |
+
• Orina de color de la Coca Cola o heces claras
|
41 |
+
• Moretones frecuentes o hemorragia
|
42 |
+
• Sarpullido o picazón
|
43 |
+
• Piel y ojos amarillentos
|
44 |
+
• Debilidad o cansancio extremos
|
45 |
+
• Hormigueo o adormecimiento en las manos o en los pies
|
46 |
+
• Mareos
|
47 |
+
|
48 |
+
NOTA: Es normal si su orina, saliva o lágrimas se vuelven color naranja. Los lentes de contacto blandos se pueden manchar.
|
49 |
+
|
rag_documents/Preguntas y respuestas sobre la tuberculosis _ TB.txt
ADDED
@@ -0,0 +1,509 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
La tuberculosis (TB) es prevenible y tratable; sin embargo, sigue siendo la enfermedad contagiosa más mortal del
|
2 |
+
mundo. Si usted tiene enfermedad de TB contagiosa signica que puede transmitir los microbios de la tuberculosis a los
|
3 |
+
demás. En los últimos años los Estados Unidos han noticado su número más bajo de casos de TB registrado; sin
|
4 |
+
embargo, todavía se enferman de tuberculosis demasiadas personas. Aún con números cada vez menores, la TB sigue
|
5 |
+
siendo un problema. Si bien la cantidad de casos de TB en los Estados Unidos ha bajado, las tasas siguen siendo más
|
6 |
+
altas entre las personas de grupos raciales y étnicos minoritarios que entre las personas de raza blanca. Esto se debe a
|
7 |
+
que ciertos grupos raciales y étnicos tienen probabilidades más altas de tener factores de riesgo relacionados con la
|
8 |
+
TB, que pueden aumentar las probabilidades de presentar la enfermedad
|
9 |
+
Este material informativo responde preguntas comunes sobre la TB. Si tiene preguntas adicionales, por favor, consulte a
|
10 |
+
su médico, enfermero u otro proveedor de atención médica.
|
11 |
+
¿Por qué sigue siendo la tuberculosis un problema en los EE. UU?
|
12 |
+
La tuberculosis (TB) se transmite de persona a persona a través del aire. Los microbios de la TB llegan al aire cuando
|
13 |
+
una persona con la enfermedad contagiosa de tuberculosis de pulmón o de garganta tose, habla o canta. Las personas
|
14 |
+
que están cerca pueden inhalar estos microbios e infectarse.
|
15 |
+
Cuando los inhalan, los microbios de la tuberculosis pueden depositarse en los pulmones y comenzar a multiplicarse. A
|
16 |
+
partir de allí, pueden propagarse a otras partes del cuerpo a través de la sangre, como al riñón, a la columna vertebral o
|
17 |
+
al cerebro.
|
18 |
+
¿Cómo se transmite la tuberculosis?
|
19 |
+
9/6/24, 1:14 PM Preguntas y respuestas sobre la tuberculosis | TB | CDC
|
20 |
+
https://www.cdc.gov/tb/esp/publications/faqs/tb-qa.htm#what-is-tb 1/14
|
21 |
+
Todas las personas pueden contraer la tuberculosis (TB). Algunas personas tienen mayor riesgo. Estas incluyen:
|
22 |
+
Personas que tienen contacto con alguien con enfermedad de TB contagiosa.
|
23 |
+
Personas nacidas en sitios o que visiten sitios, donde la enfermedad de TB sea común, incluidos México, las Filipinas,
|
24 |
+
Vietnam, la India, China, Haití, Guatemala, y otros países con altas tasas de TB.
|
25 |
+
Trabajadores de la salud y otras personas que trabajen o vivan en sitios con alto riesgo de transmisión de la TB,
|
26 |
+
como refugios para personas sin hogar, cárceles y hogares de ancianos.
|
27 |
+
¿Quiénes están en riesgo de contraer la tuberculosis?
|
28 |
+
En la mayoría de las personas que inhalan microbios de la tuberculosis (TB) y se infectan, el cuerpo es capaz de
|
29 |
+
combatir los microbios para impedir su multiplicación. Aunque los microbios se vuelvan inactivos, seguirán vivos en el
|
30 |
+
cuerpo y pueden activarse más adelante. Esto se conoce como infección de tuberculosis latente o, por sus siglas en
|
31 |
+
inglés, LTBI.
|
32 |
+
Las personas con LTBI:
|
33 |
+
No tienen síntomas.
|
34 |
+
No se sienten enfermas.
|
35 |
+
No pueden transmitir los microbios de la TB a otras personas.
|
36 |
+
Generalmente darán positivo en la prueba en sangre de la TB o la prueba de reacción cutánea de la tuberculina.
|
37 |
+
Pueden llegar a presentar la enfermedad de TB si no reciben tratamiento para la LTBI.
|
38 |
+
Las personas con LTBI no tienen síntomas y no pueden transmitir los microbios de la TB a otras personas. Sin embargo,
|
39 |
+
si esos microbios se activan y se multiplican en su cuerpo, la infección de tuberculosis latente se convertirá en la
|
40 |
+
enfermedad de TB. Por esta razón, deben recibir tratamiento para evitar la enfermedad. El tratamiento de la LTBI es
|
41 |
+
esencial para controlar la TB en los Estados Unidos porque reduce signicativamente el riesgo de progresión a la
|
42 |
+
enfermedad.
|
43 |
+
¿Qué es la infección de tuberculosis latente (LTBI)?
|
44 |
+
Si el sistema inmunitario no es capaz de impedir que los microbios de la tuberculosis (TB) se multipliquen, comenzarán
|
45 |
+
a multiplicarse en el cuerpo y causarán la enfermedad de TB. Estos microbios atacan el cuerpo, y si este ataque ocurre
|
46 |
+
en los pulmones, pueden perforarlos. Algunas personas presentan la enfermedad de TB al poco tiempo de infectarse
|
47 |
+
(dentro de unas semanas), antes de que su sistema inmunitario pueda combatir los microbios. Otras personas tendrán
|
48 |
+
la infección de tuberculosis latente y la enfermedad se podría producir años después, cuando su sistema inmunitario se
|
49 |
+
debilite por otra razón. El tratamiento de la infección de tuberculosis latente (LTBI) es ecaz para prevenir la
|
50 |
+
enfermedad.
|
51 |
+
Cuando la enfermedad de tuberculosis está en los pulmones o la garganta, puede ser contagiosa; esto signica que las
|
52 |
+
personas con la enfermedad pueden transmitir los microbios de la TB a sus familias, amigos y otras personas a su
|
53 |
+
alrededor. Cuando la TB se produce en otras partes del cuerpo, como los riñones o la columna vertebral, generalmente
|
54 |
+
no es contagiosa.
|
55 |
+
Las personas con más probabilidades de contagiarse son aquellas que pasen tiempo todos los días con alguien que
|
56 |
+
tiene la enfermedad. Estas incluyen sus familiares, amigos, compañeros de trabajo o compa��eros de escuela.
|
57 |
+
¿Qué es la enfermedad de tuberculosis?
|
58 |
+
9/6/24, 1:14 PM Preguntas y respuestas sobre la tuberculosis | TB | CDC
|
59 |
+
https://www.cdc.gov/tb/esp/publications/faqs/tb-qa.htm#what-is-tb 2/14
|
60 |
+
El tratamiento de la enfermedad requiere que se tomen varios medicamentos al inicio. Después de que el paciente tome
|
61 |
+
los medicamentos varias semanas, el médico le podrá decir cuándo ya no puede transmitir los microbios de TB a otras
|
62 |
+
personas. Para curarse, la mayoría de las personas con TB deberán tomar los medicamentos durante al menos 6 meses.
|
63 |
+
Muchas de las personas que tienen la infección de tuberculosis latente (LTBI) nunca tendrán la enfermedad. A pesar de
|
64 |
+
ello, entre aproximadamente el 5 y el 10 % presentarán la enfermedad en algún momento de su vida si su LTBI no se
|
65 |
+
trata. Se estima que los casos de LTBI no tratada que progresan a la enfermedad de TB representan aproximadamente
|
66 |
+
el 80 % de los casos de TB en los Estados Unidos. Algunas de las personas con LTBI tienen más probabilidades que
|
67 |
+
otras de presentar la enfermedad. Estas personas generalmente pertenecen a dos categorías:
|
68 |
+
Personas recientemente infectadas de microbios de TB.
|
69 |
+
Personas con afecciones, o que reciben tratamientos, que debilitan el sistema inmunitario; por ejemplo:
|
70 |
+
Infección por el VIH.
|
71 |
+
Consumo de sustancias (p. ej., consumo de drogas inyectables).
|
72 |
+
Tratamientos especializados para la artritis reumatoide o la enfermedad de Crohn.
|
73 |
+
Trasplante de órgano.
|
74 |
+
Enfermedad renal grave.
|
75 |
+
Cáncer de cabeza y cuello.
|
76 |
+
Diabetes.
|
77 |
+
Tratamientos médicos, como corticosteroides.
|
78 |
+
Silicosis.
|
79 |
+
Bajo peso corporal.
|
80 |
+
Los niños, especialmente aquellos menores de 5 años, están en mayor riesgo de presentar la enfermedad de TB una
|
81 |
+
vez infectados.
|
82 |
+
¿Quiénes están en riesgo de tener la enfermedad de tuberculosis?
|
83 |
+
Los síntomas de la enfermedad de tuberculosis (TB) dependerán de la parte del cuerpo en que los microbios se estén
|
84 |
+
multiplicando. Cuando la enfermedad está en los pulmones puede causar los siguientes síntomas:
|
85 |
+
Tos (que dura más de 3 semanas)
|
86 |
+
Tos con sangre o con esputo (la ema que sale de adentro de los pulmones)
|
87 |
+
Dolor de pecho
|
88 |
+
Fiebre
|
89 |
+
Sudores nocturnos
|
90 |
+
Escalofríos
|
91 |
+
Pérdida del apetito
|
92 |
+
Debilidad o fatiga
|
93 |
+
Pérdida de peso
|
94 |
+
Los síntomas de la enfermedad de TB en otras partes del cuerpo pueden incluir los siguientes:
|
95 |
+
La TB en los riñones puede provocar sangre en la orina.
|
96 |
+
La meningitis tuberculosa puede causar dolor de cabeza o confusión.
|
97 |
+
¿Cuáles son los síntomas de la enfermedad de tuberculosis?
|
98 |
+
9/6/24, 1:14 PM Preguntas y respuestas sobre la tuberculosis | TB | CDC
|
99 |
+
https://www.cdc.gov/tb/esp/publications/faqs/tb-qa.htm#what-is-tb 3/14
|
100 |
+
La TB en la columna vertebral puede causar dolor de espalda.
|
101 |
+
La TB en la laringe puede causar ronquera.
|
102 |
+
Para obtener información sobre cómo se trata la enfermedad de TB.
|
103 |
+
Hay diferencias importantes entre la infección de tuberculosis latente (LTBI) y la enfermedad de tuberculosis (TB).
|
104 |
+
Conocer las diferencias puede ayudarlo a entender qué esperar en caso de tener la LTBI o la enfermedad de TB. En la
|
105 |
+
tabla siguiente se explican las diferencias clave, en paralelo.
|
106 |
+
LAS PERSONAS CON INFECCIÓN DE
|
107 |
+
TUBERCULOSIS LATENTE (LTBI)
|
108 |
+
LAS PERSONAS CON ENFERMEDAD DE
|
109 |
+
TUBERCULOSIS
|
110 |
+
Tienen una pequeña cantidad de microbios de TB
|
111 |
+
en el cuerpo que están vivos pero inactivos
|
112 |
+
Tienen una gran cantidad de microbios de TB activos
|
113 |
+
en el cuerpo
|
114 |
+
No tienen síntomas Tienen síntomas que pueden incluir:
|
115 |
+
tos intensa que dura 3 semanas o más
|
116 |
+
dolor en el pecho
|
117 |
+
tos con sangre o esputo
|
118 |
+
debilidad o fatiga
|
119 |
+
pérdida de peso
|
120 |
+
falta de apetito
|
121 |
+
escalofríos
|
122 |
+
ebre
|
123 |
+
sudores nocturnos
|
124 |
+
No pueden transmitir los microbios de la TB a los
|
125 |
+
demás
|
126 |
+
Pueden transmitir los microbios de la TB a los
|
127 |
+
demás
|
128 |
+
No se sienten enfermas Pueden sentirse enfermas y pueden presentar
|
129 |
+
signos y síntomas, como tos, ebre o pérdida de
|
130 |
+
peso
|
131 |
+
Suelen dar positivo en la prueba cutánea de la
|
132 |
+
tuberculina o la prueba en sangre de la TB, lo cual
|
133 |
+
indica infección
|
134 |
+
Suelen dar positivo en la prueba cutánea de la
|
135 |
+
tuberculina o la prueba en sangre de la TB, lo cual
|
136 |
+
indica infección
|
137 |
+
Tienen radiografías de tórax normales y frotis de
|
138 |
+
esputo negativos
|
139 |
+
Pueden tener radiografías de tórax anormales, o
|
140 |
+
cultivos o frotis de esputo positivos
|
141 |
+
Deben considerar recibir tratamiento para la LTBI
|
142 |
+
para prevenir la enfermedad de TB
|
143 |
+
Necesitan tratamiento para la enfermedad de TB
|
144 |
+
¿Cuál es la diferencia entre la infección de tuberculosis latente (LTBI) y la enfermedad de
|
145 |
+
tuberculosis?
|
146 |
+
|
147 |
+
Debe hacerse una prueba de tuberculosis (TB) si:
|
148 |
+
¿Debería hacerme una prueba de tuberculosis?
|
149 |
+
9/6/24, 1:14 PM Preguntas y respuestas sobre la tuberculosis | TB | CDC
|
150 |
+
https://www.cdc.gov/tb/esp/publications/faqs/tb-qa.htm#what-is-tb 4/14
|
151 |
+
Ha pasado tiempo con alguien que usted sabe o cree que tenga enfermedad de TB contagiosa.
|
152 |
+
Nació en un país, o viaja a menudo a países donde la enfermedad de TB es común, incluidos México, las Filipinas,
|
153 |
+
Vietnam, la India, China, Haití, y Guatemala, y otros países donde la TB sea frecuente.
|
154 |
+
Ha vivido, o vive o trabaja actualmente en un entorno donde la TB sea más común, como los albergues para
|
155 |
+
personas sin hogar, las prisiones, las cárceles o los hogares de ancianos.
|
156 |
+
Es un trabajador de la salud que atiende a pacientes que tienen la enfermedad de TB.
|
157 |
+
Pertenece a una población con mayores probabilidades de tener infección de tuberculosis latente (LTBI) o
|
158 |
+
enfermedad de TB; esto incluye a las personas que no tengan buen acceso a atención médica, que tengan ingresos
|
159 |
+
bajos o que consuman drogas o alcohol de manera indebida.
|
160 |
+
Además, los niños, especialmente aquellos menores de 5 años, están en mayor riesgo de presentar la enfermedad de
|
161 |
+
TB una vez infectados. Por lo tanto, es importante detectar la infección de TB en los niños que puedan haberse
|
162 |
+
expuesto a alguien que tenga la enfermedad.
|
163 |
+
Hay dos tipos de prueba para detectar la infección de TB: la prueba en sangre y la prueba cutánea de la tuberculina. Su
|
164 |
+
proveedor de atención médica deberá decidir cuál usar. Los factores que determinarán qué prueba usar incluyen el
|
165 |
+
motivo por el cual se haga la prueba, la prueba que se tenga disponible y el costo. Se anima a los proveedores de
|
166 |
+
atención médica a usar las pruebas en sangre de la TB más nuevas para detectar la infección. Por lo general, no es
|
167 |
+
necesario hacerle las dos pruebas a la misma persona.
|
168 |
+
Pruebas en sangre de la tuberculosis
|
169 |
+
Las pruebas en sangre de la TB detectan las infecciones de microbios de la TB usando una muestra de sangre. En los
|
170 |
+
Estados Unidos hay dos pruebas en sangre de la TB aprobadas por la Administración de Alimentos y Medicamentos
|
171 |
+
FDA de los Estados Unidos que se usan:
|
172 |
+
QuantiFERON®-TB Gold Plus (QFT-Plus)
|
173 |
+
T-SPOT®.TB test (T-Spot)
|
174 |
+
Usted se puede hacer una de estas pruebas en el departamento de salud o el consultorio de su médico. El proveedor de
|
175 |
+
atención médica le extraerá una muestra de sangre y enviará la muestra a un laboratorio para que la analicen y obtener
|
176 |
+
los resultados. Si su departamento de salud usa las pruebas en sangre, solo necesitará ir una vez para que le extraigan
|
177 |
+
la muestra de sangre para la prueba.
|
178 |
+
Prueba en sangre de la TB con resultado positivo: El resultado positivo signica que usted está infectado con
|
179 |
+
microbios de TB. Necesitarán hacerle más pruebas para determinar si tiene la infección de tuberculosis latente (LTBI) o
|
180 |
+
la enfermedad de TB.
|
181 |
+
Prueba en sangre de la TB con resultado negativo: El resultado negativo signica que su sangre no reaccionó a la
|
182 |
+
prueba y que probablemente no tenga la infección de TB.
|
183 |
+
Las pruebas en sangre de la TB son las que se recomiendan para las siguientes personas:
|
184 |
+
Personas vacunadas con la BCG (vacuna de bacilo de Calmette y Guérin).
|
185 |
+
Personas para quienes sea difícil regresar para la segunda cita en la que se examina la reacción a la prueba cutánea
|
186 |
+
de la tuberculina.
|
187 |
+
Prueba cutánea de la tuberculina
|
188 |
+
¿Con qué pruebas se detecta la infección de tuberculosis?
|
189 |
+
9/6/24, 1:14 PM Preguntas y respuestas sobre la tuberculosis | TB | CDC
|
190 |
+
https://www.cdc.gov/tb/esp/publications/faqs/tb-qa.htm#what-is-tb 5/14
|
191 |
+
La prueba cutánea de la tuberculina se puede usar para averiguar si está infectado con microbios de la TB. Usted se
|
192 |
+
puede hacer esta prueba en el departamento de salud o en el consultorio de su médico. Un trabajador de la salud le
|
193 |
+
inyectará una pequeña cantidad del líquido que se usa para la prueba (llamado tuberculina o PPD, por sus siglas en
|
194 |
+
inglés) debajo de la piel, en el antebrazo. Después de 2 o 3 días, deberá regresar para que el trabajador de la salud lea
|
195 |
+
el resultado de la prueba cutánea. Es posible que tenga hinchazón en el sitio donde le inyectaron la tuberculina. El
|
196 |
+
trabajador de la salud medirá esta hinchazón y le informará si la reacción es positiva o negativa.
|
197 |
+
Prueba cutánea con reacción positiva: La reacción positiva signica que su cuerpo está infectado con microbios de la
|
198 |
+
TB. Necesitarán hacerle más pruebas para determinar si tiene la infección de tuberculosis latente o enfermedad de TB.
|
199 |
+
Prueba cutánea con reacción negativa: La reacción negativa signica que su cuerpo no reaccionó a la prueba y que
|
200 |
+
usted probablemente no tenga la LTBI o la enfermedad de TB.
|
201 |
+
Si su exposición a los microbios de la TB fue reciente, es posible que la prueba no produzca una reacción positiva
|
202 |
+
todavía. Posiblemente deba repetir la prueba cutánea después de 8 a 10 semanas desde la última vez que haya pasado
|
203 |
+
tiempo con la persona enferma. Esto se debe a que, después de infectarse, su sistema inmunitario puede tomar varias
|
204 |
+
semanas para reaccionar a la prueba. Si la segunda prueba también da negativo, lo probable es que usted no tenga la
|
205 |
+
infección de TB.
|
206 |
+
Si la prueba cutánea o la prueba en sangre de la TB produce una reacción positiva, su médico o enfermero le hará otras
|
207 |
+
pruebas para determinar si tiene la enfermedad de TB. Estas pruebas suelen incluir una radiografía de tórax. También
|
208 |
+
pueden incluir un análisis del esputo (ema) que expulsa al toser. Debido a que los microbios de la tuberculosis pueden
|
209 |
+
encontrarse en partes del cuerpo que no sean los pulmones, el médico o enfermero podría hacerle un examen de orina,
|
210 |
+
tomarle muestras de tejido o hacer otras pruebas. Sin tratamiento, la infección de tuberculosis latente (LTBI) puede
|
211 |
+
progresar a la enfermedad de TB. Si usted tiene LTBI, debe recibir tratamiento para prevenir la enfermedad. Si tiene la
|
212 |
+
enfermedad de TB, deberá tomar medicamentos para tratarla.
|
213 |
+
¿Qué pasa si la prueba de infección de TB me da positivo?
|
214 |
+
La BCG es una vacuna contra la TB. En los Estados Unidos su uso no es generalizado. Muchas personas nacidas fuera
|
215 |
+
de los Estados Unidos están vacunadas contra la tuberculosis con la BCG.
|
216 |
+
En otros países, donde la TB es más frecuente, es común que se vacune a los bebés y niños pequeños. Esto los protege
|
217 |
+
contra las formas graves de la enfermedad de TB, como la meningitis tuberculosa. No se cree que la vacuna proteja
|
218 |
+
contra la TB de los pulmones, que es la forma más común que se encuentra en los Estados Unidos.
|
219 |
+
La prueba cutánea de la TB puede dar una reacción positiva en algunas personas vacunadas con la BCG, aunque no
|
220 |
+
estén infectadas. Sin embargo, no hay manera de saber si la reacción positiva se debe a la BCG o a una verdadera
|
221 |
+
infección de TB. Cuando la prueba cutánea se usa en personas vacunadas y la reacción es positiva, siempre se las debe
|
222 |
+
evaluar en mayor profundidad como si no estuvieran vacunadas, para determinar si tienen la enfermedad de TB.
|
223 |
+
A diferencia de las pruebas cutáneas de la TB, las pruebas en sangre no se ven afectadas por la vacunación previa con
|
224 |
+
la BCG. Por lo tanto, se preeren las pruebas en sangre para las personas que estén vacunadas contra la tuberculosis.
|
225 |
+
¿Qué pasa si estoy vacunado con la BCG (bacilo de Calmette y Guérin)?
|
226 |
+
Si tengo la infección de tuberculosis latente (LTBI) ¿cómo puedo evitar la enfermedad de
|
227 |
+
tuberculosis?
|
228 |
+
|
229 |
+
9/6/24, 1:14 PM Preguntas y respuestas sobre la tuberculosis | TB | CDC
|
230 |
+
https://www.cdc.gov/tb/esp/publications/faqs/tb-qa.htm#what-is-tb 6/14
|
231 |
+
Sin tratamiento, la infección de tuberculosis latente (LTBI) puede progresar a la enfermedad de TB. Si usted tiene la
|
232 |
+
LTBI, debe recibir tratamiento para evitar la enfermedad aunque no se sienta enfermo. El tratamiento de la LTBI es
|
233 |
+
esencial para prevenir la enfermedad de TB porque reduce signicativamente su riesgo de progresión.
|
234 |
+
El tratamiento de la LTBI es ecaz para la prevención de la enfermedad. Hay varias opciones para el tratamiento de la
|
235 |
+
LTBI. Se han logrado avances en cuanto a la duración del tratamiento de la LTBI, acortándola de 6-9 meses a 3-4
|
236 |
+
meses. Estos esquemas de tratamiento cortos son ecaces, son seguros y tienen tasas de compleción más altas.
|
237 |
+
Si usted tiene LTBI y pertenece a un grupo de mayor riesgo, es aún más urgente que tome medicamentos para que no
|
238 |
+
presente la enfermedad de TB. Los siguientes medicamentos para la TB se usan de manera independiente o combinada
|
239 |
+
para el tratamiento de la LTBI:
|
240 |
+
Isoniacida (INH)
|
241 |
+
Rifapentina (RPT)
|
242 |
+
Rifampina (RIF)
|
243 |
+
Los CDC y la Asociación Nacional de Controladores de Tuberculosis recomiendan una de las siguientes opciones de
|
244 |
+
tratamiento:
|
245 |
+
Tres meses de isoniacida más rifapentina una vez a la semana (3HP).
|
246 |
+
Cuatro meses de rifapentina diaria (4R).
|
247 |
+
Tres meses de isoniacida más rifampina diarias (3HR).
|
248 |
+
Si ninguno de los esquemas de tratamiento anteriores son una opción para usted, existen esquemas alternativos que
|
249 |
+
incluyen 6 o 9 meses de isoniacida. Si toma isoniacida, el médico puede indicarle que la tome con vitamina B6. Él o ella
|
250 |
+
podrá determinar cuál de las opciones de tratamiento es la mejor para su situación. Es posible que se deba modicar el
|
251 |
+
tratamiento, si los microbios que causaron la enfermedad de TB de la persona con la que tuvo contacto son resistentes
|
252 |
+
a la isoniacida o a la rifampina, dos de los medicamentos más importantes para el tratamiento de la LTBI y la
|
253 |
+
enfermedad de TB. Esto signica que esos medicamentos ya no pueden destruir los microbios de TB.
|
254 |
+
A veces se indica el tratamiento de la LTBI a una persona, incluso si su prueba en sangre o su prueba cutánea de la TB
|
255 |
+
da negativo. Esto sucede a menudo con los bebés, los niños y las personas infectadas por el VIH que hayan pasado
|
256 |
+
tiempo recientemente con alguien que tenía la enfermedad de TB. La razón es que las personas de estos grupos tienen
|
257 |
+
un riesgo muy alto de presentar la enfermedad de TB poco después de haber sido infectadas por los microbios de la
|
258 |
+
TB.
|
259 |
+
Si empieza el tratamiento para la LTBI, deberá visitar al médico o enfermero en forma regular. Es importante que tome
|
260 |
+
todos los medicamentos según las indicaciones. El médico o enfermero le hará seguimiento para ver cómo sigue.
|
261 |
+
La mayoría de las personas pueden tomar los medicamentos para la LTBI sin ningún problema; sin embargo, a veces se
|
262 |
+
producen efectos secundarios. Algunos de los efectos secundarios son problemas menores. Por ejemplo, los
|
263 |
+
medicamentos rifampina o rifapentina pueden cambiar el color de los líquidos corporales —como la orina, la saliva, las
|
264 |
+
lágrimas o el sudor y la leche materna— volviéndolos anaranjados. Esta coloración anaranjada de los líquidos
|
265 |
+
corporales es algo previsto e inofensivo. Es normal y el color puede desaparecer con el tiempo. Si usa lentes de
|
266 |
+
contacto, el médico o enfermero puede aconsejarle que use lentes blandos, porque pueden teñirse permanentemente.
|
267 |
+
Si tiene alguno de estos efectos secundarios, puede seguir tomando sus medicamentos.
|
268 |
+
¿Cuáles son los efectos secundarios de los medicamentos que tratan la infección de
|
269 |
+
tuberculosis latente (LTBI)?
|
270 |
+
|
271 |
+
9/6/24, 1:14 PM Preguntas y respuestas sobre la tuberculosis | TB | CDC
|
272 |
+
https://www.cdc.gov/tb/esp/publications/faqs/tb-qa.htm#what-is-tb 7/14
|
273 |
+
Si tiene un efecto secundario grave, llame al médico o enfermero inmediatamente. Es posible que le indique que deje
|
274 |
+
de tomar los medicamentos para la LTBI o que regrese al centro médico para hacerse pruebas. Los efectos secundarios
|
275 |
+
graves incluyen:
|
276 |
+
Mareos o sensación de desmayo
|
277 |
+
Pérdida del apetito
|
278 |
+
Síntomas similares a los de la inuenza (gripe)
|
279 |
+
Diarrea intensa o heces de color claro
|
280 |
+
Dicultad para respirar
|
281 |
+
Sentimientos de tristeza o depresión
|
282 |
+
Fiebre
|
283 |
+
Pérdida de peso sin causa conocida
|
284 |
+
Orina marrón (como el color del café o la coca cola)
|
285 |
+
Coloración amarilla en la piel o los ojos
|
286 |
+
Sarpullido
|
287 |
+
Hormigueo o sensación de pinchazos persistente en las manos y los pies
|
288 |
+
Cansancio o debilidad persistentes que duran 3 días o más
|
289 |
+
Dolor de estómago
|
290 |
+
Moretones o sangrados que ocurren con facilidad
|
291 |
+
Dolor en las articulaciones
|
292 |
+
Náuseas
|
293 |
+
Vómitos
|
294 |
+
Para evitar las interacciones con otros medicamentos, le debe dar a su proveedor de atención médica una lista de los
|
295 |
+
medicamentos que esté tomando actualmente. Algunos anticonceptivos orales (píldoras anticonceptivas) podrían ser
|
296 |
+
menos ecaces cuando se toman con los medicamentos para la TB. Esto se debe a que los medicamentos para la TB, a
|
297 |
+
veces, pueden afectar el funcionamiento de las píldoras anticonceptivas y posiblemente hacerlas menos ecaces. Si
|
298 |
+
usted toma píldoras anticonceptivas, hable con su médico antes de comenzar a tomar ningún medicamento nuevo.
|
299 |
+
Puede encontrar más información sobre los efectos secundarios de los medicamentos para la TB en la
|
300 |
+
página web de los CDC sobre los eventos adversos del tratamiento de la TB.
|
301 |
+
Advertencia: Consumir bebidas alcohólicas, como vino, cerveza o licor, mientras se toman los medicamentos para la TB
|
302 |
+
puede ser peligroso. Para obtener más información, consulte al médico o enfermero.
|
303 |
+
2. Esquema de 4 meses de rifampina diaria (4R) para la infección de tuberculosis latente: registro de
|
304 |
+
medicamentos y hoja de vericación de síntomas. (Disponible en inglés).
|
305 |
+
3. Esquema de 3 meses de isoniacida más rifampina diarias (3HR) para la infección de tuberculosis latente:
|
306 |
+
registro de medicamentos y hoja de vericación de síntomas. (Disponible en inglés).
|
307 |
+
Esquemas posológicos para el tratamiento de la infección de tuberculosis latente
|
308 |
+
Cómo decidir cuándo se debe tratar la infección de tuberculosis latente
|
309 |
+
Cómo tratar la LTBI con los esquemas cortos
|
310 |
+
¿Qué pasa si tengo la infección por el VIH?
|
311 |
+
9/6/24, 1:14 PM Preguntas y respuestas sobre la tuberculosis | TB | CDC
|
312 |
+
https://www.cdc.gov/tb/esp/publications/faqs/tb-qa.htm#what-is-tb 8/14
|
313 |
+
Si usted tiene la infección por el VIH y la infección de tuberculosis latente (LTBI), necesita recibir tratamiento lo antes
|
314 |
+
posible para prevenir la enfermedad de TB. Las personas que tienen la infección por el VIH y además LTBI sin tratar
|
315 |
+
tienen muchas más probabilidades de presentar la enfermedad de TB en algún momento de su vida que aquellas sin el
|
316 |
+
VIH. Entre las personas con LTBI, la infección por el VIH es el factor de riesgo conocido más preponderante de
|
317 |
+
progresión a la enfermedad de TB. Todas las personas con infección por el VIH deben hacerse una prueba de LTBI para
|
318 |
+
averiguar si la tienen y, de ser necesario, buscar tratamiento con prontitud. Hay varios esquemas de tratamiento de la
|
319 |
+
LTBI ecaces para las personas que tienen el VIH.
|
320 |
+
Si usted se expuso a alguien que tenía la enfermedad de TB, puede haberse infectado de microbios de la TB, pero no
|
321 |
+
los podría propagar en forma inmediata. Solo las personas que tienen la enfermedad de TB pueden propagar los
|
322 |
+
microbios a los demás. Antes de que la propagación fuera posible, usted debe haber inhalado microbios de la TB y
|
323 |
+
contraído la infección. Después, los microbios deben haberse multiplicado en su cuerpo y causado enfermedad de TB
|
324 |
+
contagiosa. Sucedido eso, sería posible propagar los microbios de la TB.
|
325 |
+
En la mayoría de las personas que inhalan microbios de la TB y se infectan, el cuerpo puede combatir los microbios e
|
326 |
+
impedir que se multipliquen. En ese caso, los microbios estarían en estado inactivo, pero seguirían vivos en su cuerpo y
|
327 |
+
podrían activarse más adelante. Este tipo de infección de TB se conoce como infección de tuberculosis latente (LTBI).
|
328 |
+
Las personas que tienen la LTBI no pueden transmitir estos microbios a otras personas. Además, pueden tratar la
|
329 |
+
infección para evitar que se convierta en la enfermedad de TB.
|
330 |
+
Si me expuse a alguien que tenía la enfermedad de tuberculosis, ¿puedo contagiar a otros?
|
331 |
+
¡Hay buenas noticias para las personas con enfermedad de tuberculosis (TB)! Casi siempre se puede tratar y curar con
|
332 |
+
medicamentos. Pero los medicamentos se deben tomar según las indicaciones del médico o enfermero.
|
333 |
+
Si usted tiene la enfermedad, deberá tomar varios medicamentos distintos para la TB. La razón es que hay muchos
|
334 |
+
microbios para destruir. Usar varios medicamentos a la vez es más ecaz para destruir a todos los microbios de la TB y
|
335 |
+
prevenir que se hagan resistentes a los medicamentos. Se les dice “resistentes” a las bacterias de la TB cuando los
|
336 |
+
medicamentos ya no pueden destruirlas.
|
337 |
+
Los medicamentos que se usan más comúnmente para el tratamiento de la enfermedad de TB son:
|
338 |
+
Isoniacida (INH)
|
339 |
+
Rifampina (RIF)
|
340 |
+
Etambutol (EMB)
|
341 |
+
Pirazinamida (PZA)
|
342 |
+
Si usted tiene enfermedad de TB en los pulmones o la garganta, es probable que su enfermedad sea contagiosa. Debe
|
343 |
+
quedarse en su casa y no ir al trabajo o la escuela, para que no pueda transmitir los microbios de TB a otras personas.
|
344 |
+
Después de que tome los medicamentos durante varias semanas se sentirá mejor y es posible que su enfermedad ya no
|
345 |
+
sea contagiosa. El médico o enfermero le indicará cuándo puede volver al trabajo, a la escuela o a ver a sus amigos.
|
346 |
+
El hecho de tener la enfermedad de TB no debe impedirle llevar una vida normal. Cuando las personas ya no son
|
347 |
+
contagiosas o ya no se sienten enfermas, generalmente pueden volver a hacer las mismas cosas que hacían antes de la
|
348 |
+
enfermedad. Si usted toma los medicamentos según las indicaciones del médico o enfermero, deberían destruir todos
|
349 |
+
los microbios de la TB. Esto evitará que usted vuelva a tener la enfermedad.
|
350 |
+
¿Cómo se trata la enfermedad de tuberculosis?
|
351 |
+
9/6/24, 1:14 PM Preguntas y respuestas sobre la tuberculosis | TB | CDC
|
352 |
+
https://www.cdc.gov/tb/esp/publications/faqs/tb-qa.htm#what-is-tb 9/14
|
353 |
+
Si usted está tomando medicamentos para la enfermedad de TB, debe tomarlos según las indicaciones del médico o
|
354 |
+
enfermero. Los medicamentos para la TB pueden provocar efectos secundarios. Algunos son problemas menores. Otros
|
355 |
+
son más serios. Si tiene un efecto secundario grave, llame al médico o enfermero inmediatamente. Es posible que le
|
356 |
+
indique que deje de tomar los medicamentos para la TB o que regrese al centro médico para hacerse pruebas. Los
|
357 |
+
efectos secundarios graves incluyen:
|
358 |
+
Sarpullido
|
359 |
+
Visión borrosa o cambios en la vista
|
360 |
+
Dolor de estómago
|
361 |
+
Orina de color marrón o heces de color claro
|
362 |
+
Cansancio
|
363 |
+
Fiebre durante 3 días o más
|
364 |
+
Síntomas similares a los de la inuenza (gripe)
|
365 |
+
Falta de apetito
|
366 |
+
Náuseas
|
367 |
+
Vómitos
|
368 |
+
Coloración amarilla en la piel o los ojos
|
369 |
+
Mareos
|
370 |
+
Sensación de hormigueo o adormecimiento alrededor de la boca
|
371 |
+
Sensación persistente de pinchazos en las manos y los pies
|
372 |
+
Malestar estomacal
|
373 |
+
Dolores en las articulaciones
|
374 |
+
Moretones o sangrados que ocurren con facilidad
|
375 |
+
Algunos de los efectos secundarios son problemas menores. Por ejemplo, la rifampina pueden cambiar el color de los
|
376 |
+
líquidos corporales —como la orina, la saliva, las lágrimas o el sudor y la leche materna— volviéndolos anaranjados.
|
377 |
+
Esta coloración anaranjada de los líquidos corporales es algo previsto e inofensivo. Es normal y el color puede
|
378 |
+
desaparecer con el tiempo. Si usa lentes de contacto, el médico o enfermero puede aconsejarle que use lentes blandos,
|
379 |
+
porque pueden teñirse permanentemente. Si tiene alguno de estos efectos secundarios, puede seguir tomando sus
|
380 |
+
medicamentos.
|
381 |
+
Los medicamentos que se recetan para el tratamiento de la enfermedad de TB pueden tener interacciones con otros
|
382 |
+
medicamentos. Para evitarlas, le debe dar a su proveedor de atención médica una lista de los medicamentos que esté
|
383 |
+
tomando actualmente.
|
384 |
+
Por ejemplo, pueden interactuar con los anticonceptivos orales (píldoras anticonceptivas) y posiblemente hacerlos
|
385 |
+
menos ecaces. Si usted toma píldoras anticonceptivas, consulte al médico sobre métodos de anticoncepción
|
386 |
+
alternativos mientras esté tomando los medicamentos para la TB. Si usted está tomando metadona (que se usa para
|
387 |
+
tratar la drogadicción), es posible que tenga síntomas de abstinencia. Es posible que el médico o enfermero deba
|
388 |
+
ajustarle la dosis de la metadona.
|
389 |
+
Puede encontrar más información sobre los efectos secundarios de los medicamentos para la TB en la página web de
|
390 |
+
los CDC sobre los eventos adversos del tratamiento de la TB.
|
391 |
+
¿Cuáles son los efectos secundarios de los medicamentos que tratan la enfermedad de
|
392 |
+
tuberculosis?
|
393 |
+
|
394 |
+
9/6/24, 1:14 PM Preguntas y respuestas sobre la tuberculosis | TB | CDC
|
395 |
+
https://www.cdc.gov/tb/esp/publications/faqs/tb-qa.htm#what-is-tb 10/14
|
396 |
+
La destrucción de los microbios de la TB es lenta. El tratamiento de la infección de tuberculosis latente (LTBI) toma al
|
397 |
+
menos 3 meses (y posiblemente más tiempo, según los medicamentos que tome) para destruirlos.
|
398 |
+
En el caso de la enfermedad de TB, los medicamentos generalmente toman 6 meses o más para destruir todos los
|
399 |
+
microbios. Es probable que comience a sentirse mejor solo pocas semanas después de comenzar el tratamiento, pero
|
400 |
+
¡tenga cuidado! Los microbios de la TB seguirán estando vivos en su cuerpo aunque usted se sienta mejor. Debe
|
401 |
+
continuar tomando los medicamentos hasta que todos los microbios hayan sido destruidos, aunque pueda sentirse
|
402 |
+
mejor y ya no tenga síntomas de la enfermedad.
|
403 |
+
Puede ser muy peligroso dejar de tomar los medicamentos o no tomarlos con regularidad. Esto hará que los microbios
|
404 |
+
vuelvan a multiplicarse, y usted seguirá enfermo durante más tiempo. También es posible que se vuelvan resistentes a
|
405 |
+
los medicamentos que esté tomando. Si los medicamentos dejan de funcionar, posiblemente necesite medicamentos
|
406 |
+
nuevos para destruir los microbios. Los nuevos medicamentos se deberán tomar durante más tiempo y, por lo general,
|
407 |
+
tienen efectos secundarios más graves.
|
408 |
+
Si su enfermedad vuelve a ser contagiosa, usted podría transmitir microbios de TB a sus familiares, sus amigos o a
|
409 |
+
cualquier persona que pase tiempo con usted. Es muy importante que tome todos los medicamentos según las
|
410 |
+
indicaciones del médico o enfermero.
|
411 |
+
¿Por qué debo tomar los medicamentos para la tuberculosis tanto tiempo?
|
412 |
+
En algunas ocasiones, las microbios de la TB son resistentes a los medicamentos que se usan para tratar la enfermedad
|
413 |
+
de TB. Esto signica que los medicamentos ya no pueden destruir los microbios.
|
414 |
+
La tuberculosis multirresistente (o MDR TB, por sus siglas en inglés) es causada por microbios de TB que son
|
415 |
+
resistentes a al menos dos de los medicamentos más importantes para el tratamiento de la TB: la isoniacida y la
|
416 |
+
rifampina.
|
417 |
+
Existe una forma más grave de MDR TB que se llama tuberculosis extremadamente resistente (XDR TB, por sus siglas
|
418 |
+
en inglés). Este es un tipo raro de tuberculosis que es resistente a casi todos los medicamentos que se utilizan para
|
419 |
+
tratarla.
|
420 |
+
Si usted no toma sus medicamentos según las indicaciones del médico o enfermero, los microbios pueden volverse
|
421 |
+
resistentes determinados medicamentos. Los microbios multirresistentes pueden, además, infectar a quienes hayan
|
422 |
+
pasado tiempo con la persona que estaba enferma de MDR TB o XDR TB.
|
423 |
+
La tuberculosis resistente a los medicamentos es más común en las personas que:
|
424 |
+
Hayan pasado tiempo con alguien que estaba enfermo de tuberculosis resistente a los medicamentos.
|
425 |
+
No tomen todos sus medicamentos según las indicaciones del médico o enfermero.
|
426 |
+
Vuelvan a tener enfermedad de TB después de haber tomado medicamentos para tratarla en el pasado.
|
427 |
+
Vengan de áreas donde la TB resistente a los medicamentos sea común.
|
428 |
+
Las personas que tienen MDR TB o XDR TB deben ser tratadas con medicamentos especiales. El tratamiento dura más
|
429 |
+
que el de la TB común, y los medicamentos pueden causar más efectos secundarios. Las personas con estos tipos de
|
430 |
+
TB están en mayor riesgo de morir a causa de la enfermedad. Deben, además, atenderse con un experto en TB que
|
431 |
+
pueda seguir su tratamiento estrechamente para asegurarse de que esté funcionando.
|
432 |
+
¿Qué es la tuberculosis multirresistente (MDR TB) y la tuberculosis extremadamente
|
433 |
+
resistente (XDR TB)?
|
434 |
+
|
435 |
+
9/6/24, 1:14 PM Preguntas y respuestas sobre la tuberculosis | TB | CDC
|
436 |
+
https://www.cdc.gov/tb/esp/publications/faqs/tb-qa.htm#what-is-tb 11/14
|
437 |
+
La mejor forma de acordarse de tomar sus medicamentos es mediante el tratamiento de observación directa (o DOT,
|
438 |
+
por sus siglas en inglés); esto es particularmente cierto en el caso de la enfermedad de TB. Si usted obtiene DOT, se
|
439 |
+
reunirá con un trabajador de la salud todos los días o varias veces a la semana. Se pondrán de acuerdo en dónde
|
440 |
+
reunirse o se reunirán o por medios electrónicos. El sitio donde se encuentren puede ser el centro médico de atención
|
441 |
+
para la TB, su casa, su trabajo o cualquier otro lugar conveniente. Tomará sus medicamentos en ese lugar, mientras un
|
442 |
+
trabajador de la salud lo observa. Algunos programas de TB ahora usan métodos de DOT electrónicos, tanto para la
|
443 |
+
enfermedad de TB como para la infección de tuberculosis latente (LTBI). El tratamiento de observación directa
|
444 |
+
electrónico (eDOT, por sus siglas en inglés) es una alternativa al DOT en persona. Si hay DOT electrónico disponible en
|
445 |
+
su área y usted reúne los requisitos para recibirlo, un trabajador de la salud lo observará remotamente, a través de un
|
446 |
+
teléfono inteligente u otro dispositivo con video, mientras toma los medicamentos. Independientemente de que sea en
|
447 |
+
persona o con un dispositivo electrónico, el DOT lo ayuda a acordarse de tomar sus medicamentos y a completar su
|
448 |
+
tratamiento. Esto signica que usted se recuperará lo antes posible.
|
449 |
+
El trabajador de la salud también se asegurará de que los medicamentos estén funcionando del modo esperado,
|
450 |
+
vigilará si usted presenta efectos secundarios y responderá las preguntas que tenga sobre la TB.
|
451 |
+
Si usted no recibe DOT, aún deberá ver al médico o enfermero en distintos momentos del tratamiento para asegurarse
|
452 |
+
de que todo esté funcionando bien. Esto continuará hasta que se cure.
|
453 |
+
¿Qué es el tratamiento de observación directa (DOT)?
|
454 |
+
La única forma de mejorarse es tomando los medicamentos para la TB exactamente según las indicaciones del médico
|
455 |
+
o enfermero. ¡Esto podría no ser fácil! Si usted tiene LTBI, tomará medicamentos durante 3 meses o más. Si usted tiene
|
456 |
+
enfermedad de TB, por lo general tomará medicamentos durante 6 meses o más.
|
457 |
+
Tener una rutina puede ayudarlo a acordarse de tomar los medicamentos, tal como se lo indicaron. Las siguientes son
|
458 |
+
algunas de las cosas que puede hacer para acordarse de tomar sus medicamentos, sean para la LTBI o la enfermedad
|
459 |
+
de TB:
|
460 |
+
Tomar las pastillas todos los días a la misma hora, por ejemplo, antes del desayuno, durante un descanso que tome
|
461 |
+
regularmente o después de lavarse los dientes.
|
462 |
+
Pedirle a un familiar o amigo que le recuerde tomar sus píldoras.
|
463 |
+
Tachar los días en un calendario cuando tome los medicamentos.
|
464 |
+
Poner sus dosis en un pastillero semanal y mantenerlo junto a la cama o llevarlo en su bolso o en un bolsillo.
|
465 |
+
Usar un registro de medicamentos para organizar y manejar las pastillas que toma. En el sitio web de los CDC hay
|
466 |
+
registros de medicamentos para la LTBI para imprimir. Estas son hojas con espacios donde puede anotar su calendario
|
467 |
+
de tratamiento, la cantidad de pastillas que debe tomar cada semana y la información de contacto del médico o centro
|
468 |
+
médico. Para descargar o imprimir estos registros, visite la página web de los CDC de materiales educativos sobre la
|
469 |
+
TB.
|
470 |
+
NOTA: recuerde mantener todos los medicamentos fuera del alcance de los niños.
|
471 |
+
Si un día se olvida de tomar las pastillas, sáltese esa dosis y tome la dosis siguiente. Dígale al médico o enfermero si se
|
472 |
+
ha saltado alguna dosis. También puede llamarlo para que le dé instrucciones.
|
473 |
+
¿Qué puedo hacer para acordarme de tomar los medicamentos para la tuberculosis si no
|
474 |
+
estoy haciendo tratamiento de observación directa (DOT)?
|
475 |
+
|
476 |
+
9/6/24, 1:14 PM Preguntas y respuestas sobre la tuberculosis | TB | CDC
|
477 |
+
https://www.cdc.gov/tb/esp/publications/faqs/tb-qa.htm#what-is-tb 12/14
|
478 |
+
Si usted tiene enfermedad de tuberculosis (TB) contagiosa, la forma más importante en que puede evitar la transmisión
|
479 |
+
de los microbios es tomando todos los medicamentos exactamente como lo indique el médico enfermero. Además,
|
480 |
+
debe ir a todas sus citas médicas. El médico o enfermero necesita vigilar cómo sigue. Para esto a veces se requiere otra
|
481 |
+
radiografía de tórax o prueba de su esputo (la ema del fondo de los pulmones que sale cuando tose). Estas pruebas
|
482 |
+
mostrarán si los medicamentos están funcionando. También mostrarán si todavía puede transmitir microbios de la TB a
|
483 |
+
otras personas. Asegúrese de decirle al proveedor de atención médica si piensa que algo anda mal.
|
484 |
+
Si está lo sucientemente enfermo por la TB como para ir al hospital, probablemente lo pondrán en una habitación
|
485 |
+
especial. Estas habitaciones tienen rejillas de ventilación que evitan la propagación de los microbios de TB a otras
|
486 |
+
habitaciones. El personal asignado a estas habitaciones debe usar una mascarilla especial para protegerse de los
|
487 |
+
microbios. Usted deberá permanecer en la habitación para que no transmita microbios de la TB a otras personas.
|
488 |
+
Si está en su casa mientras la enfermedad es contagiosa, hay algunas medidas que puede tomar para proteger a las
|
489 |
+
personas que estén cerca suyo:
|
490 |
+
Tome sus medicamentos según las indicaciones. ¡Esto es muy importante!
|
491 |
+
Cúbrase la boca con un pañuelo desechable siempre que tosa, estornude o se ría. Ponga el pañuelo usado en una
|
492 |
+
bolsa, ciérrela y bótela.
|
493 |
+
Manténgase apartado de los demás y evite el contacto cercano con todos. Duerma en una habitación alejada del
|
494 |
+
resto de sus familiares. Evite recibir visitas en su casa.
|
495 |
+
No vaya al trabajo o a la escuela.
|
496 |
+
Abra las ventanas de su habitación para que el aire salga (si no hace demasiado frío). La TB se propaga en los
|
497 |
+
lugares cerrados pequeños donde no circula el aire. Coloque un ventilador en la ventana para que sople hacia afuera
|
498 |
+
(extraiga) el aire que podría estar cargado de microbios de TB. Si en la habitación hay otras ventanas, ábralas
|
499 |
+
también para que el ventilador pueda mover el aire fresco hacia adentro. Esto reducirá las probabilidades de que los
|
500 |
+
microbios de la TB se queden dentro de la habitación e infecten a alguien que respire el aire.
|
501 |
+
Recuerde, la TB se propaga a través del aire. Los microbios de la TB no pueden infectar a las personas cuando se dan la
|
502 |
+
mano o se sientan en el asiento del inodoro, ni cuando comparten platos y utensilios con alguien que tiene TB.
|
503 |
+
Después de que usted tome los medicamentos durante unas 2 o 3 semanas, es posible que su enfermedad deje de ser
|
504 |
+
contagiosa. El médico o enfermero le indicará cuándo puede volver al trabajo, a la escuela o a ver a sus amigos.
|
505 |
+
Recuerde que solo mejorará si toma los medicamentos exactamente según las indicaciones del médico o enfermero.
|
506 |
+
Trate de recordar con quiénes ha pasado tiempo, como familiares, amigos cercanos y compañeros de trabajo. Es posible
|
507 |
+
que el departamento de salud local deba hacerles una prueba de infección de TB. La TB es particularmente peligrosa
|
508 |
+
para los niños y las personas con infección por el VIH. Si se infectan de microbios de TB, necesitan tomar medicamentos
|
509 |
+
de inmediato para evitar tener la enfermedad de TB
|
rag_documents/Tuberculosis - Diagnóstico y tratamiento - Mayo Clinic.txt
ADDED
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Durante la exploración física, el médico te examinará los ganglios linfáticos para
|
2 |
+
detectar hinchazón y escuchará los sonidos de tus pulmones mientras respiras
|
3 |
+
con un estetoscopio.
|
4 |
+
La herramienta de diagnóstico más usada para la tuberculosis es una prueba
|
5 |
+
cutánea, aunque se están volviendo más comunes los análisis de sangre. Se
|
6 |
+
inyecta una pequeña cantidad de una sustancia llamada tuberculina debajo de la
|
7 |
+
piel en el interior del antebrazo. Deberías sentir solo un ligero pinchazo de aguja.
|
8 |
+
Dentro de las 48 a 72 horas, un profesional de atención médica controlará si se
|
9 |
+
hinchó el sitio de la inyección en tu brazo. Un bultito elevado, rojo y duro signica
|
10 |
+
que es posible que estés infectado con tuberculosis. El tamaño del bultito
|
11 |
+
determina si los resultados de la prueba son signicativos.
|
12 |
+
|
13 |
+
Pruebas de tuberculosis
|
14 |
+
El proveedor de atención médica pedirá que se realicen pruebas si:
|
15 |
+
Sospecha que tienes tuberculosis.
|
16 |
+
Es probable que hayas estado expuesto a una persona con tuberculosis
|
17 |
+
activa.
|
18 |
+
Tienes riesgos de salud para la tuberculosis activa.
|
19 |
+
El proveedor de atención médica determinará si la mejor opción es una prueba
|
20 |
+
cutánea o un análisis de sangre.
|
21 |
+
Prueba cutánea
|
22 |
+
Se inyecta una pequeña cantidad de una sustancia llamada tuberculina debajo de
|
23 |
+
la piel, en la parte interior del antebrazo. Dentro de las 48 a 72 horas, un
|
24 |
+
profesional de atención médica revisará si se hinchó el sitio de la inyección en tu
|
25 |
+
brazo. El tamaño de la piel levantada se utiliza para determinar una prueba positiva
|
26 |
+
o negativa.
|
27 |
+
Esta prueba consiste en ver si tu sistema inmunitario reacciona, o si ha generado
|
28 |
+
un anticuerpo, ante la tuberculosis. Una prueba positiva indica si tienes una
|
29 |
+
infección latente por tuberculosis o una tuberculosis activa. Las personas
|
30 |
+
vacunadas contra la tuberculosis pueden dar positivo en la prueba aunque no
|
31 |
+
tengan ninguna infección.
|
32 |
+
Una prueba negativa signica que tu cuerpo no ha reaccionado a la prueba. No
|
33 |
+
signica necesariamente que no tengas una infección.
|
34 |
+
Análisis de sangre
|
35 |
+
Los análisis de sangre pueden conrmar o descartar la forma activa o latente de la
|
36 |
+
tuberculosis. Estos análisis miden la reacción de tu sistema inmunitario a las
|
37 |
+
bacterias de la tuberculosis.
|
38 |
+
Para estas pruebas, solo necesitas ir una vez al consultorio. El análisis de sangre
|
39 |
+
puede ser útil si tienes un riesgo alto de una infección con tuberculosis, pero tu
|
40 |
+
resultado de la prueba cutánea resultó negativo, o te dieron recientemente la
|
41 |
+
vacuna con el bacilo de Calmette-Guérin.
|
42 |
+
9/6/24, 1:08 PM Tuberculosis - Diagnóstico y tratamiento - Mayo Clinic
|
43 |
+
https://www.mayoclinic.org/es/diseases-conditions/tuberculosis/diagnosis-treatment/drc-20351256 2/12
|
44 |
+
Pruebas porimágenes
|
45 |
+
Si tuviste un resultado positivo en una prueba cutánea, es probable que el médico
|
46 |
+
pida una radiografía o una exploración por tomografía computarizada de pecho.
|
47 |
+
Estas pruebas pueden mostrar manchas blancas en los pulmones donde el
|
48 |
+
sistema inmunitario ha encapsulado las bacterias de la tuberculosis o pueden
|
49 |
+
revelar cambios en los pulmones causados por una forma activa de tuberculosis.
|
50 |
+
Examen de esputo
|
51 |
+
Si la radiografía torácica revela signos de tuberculosis, el médico podría tomar
|
52 |
+
muestras de esputo, la mucosidad que despides cuando toses. Las muestras se
|
53 |
+
analizan para detectar la bacteria de la tuberculosis.
|
54 |
+
Las muestras de esputo también se pueden utilizar para buscar cepas de
|
55 |
+
tuberculosis resistentes a los medicamentos. Esto ayuda a tu doctor a elegir los
|
56 |
+
medicamentos que probablemente funcionen mejor. Los resultados de estos
|
57 |
+
exámenes pueden tardar entre cuatro y ocho semanas.
|
58 |
+
Otros análisis de laboratorio
|
59 |
+
Algunos análisis de laboratorio que pueden ser necesarios incluyen los siguientes:
|
60 |
+
Prueba de aliento.
|
61 |
+
Procedimiento para extraer esputo de los pulmones con una sonda especial.
|
62 |
+
Análisis de orina.
|
63 |
+
Análisis del líquido que rodea la columna vertebral y el cerebro, llamado
|
64 |
+
líquido cefalorraquídeo.
|
65 |
+
Aviso
|
66 |
+
9/6/24, 1:08 PM Tuberculosis - Diagnóstico y tratamiento - Mayo Clinic
|
67 |
+
https://www.mayoclinic.org/es/diseases-conditions/tuberculosis/diagnosis-treatment/drc-20351256 3/12
|
68 |
+
Mayo Clinic no respalda empresas ni
|
69 |
+
productos. Los ingresos por publicidad
|
70 |
+
respaldan nuestra misión sin nes de lucro.
|
71 |
+
Avisos comerciales y patrocinio
|
72 |
+
Política Oportunidades
|
73 |
+
Opciones de anuncios
|
74 |
+
Más información
|
75 |
+
Tratamiento
|
76 |
+
Si tienes tuberculosis latente, tu médico podría recomendarte un tratamiento con
|
77 |
+
medicamentos si presentas riesgos altos de tener tuberculosis activa. Para la
|
78 |
+
tuberculosis activa, debes tomar antibióticos por lo menos por seis a nueve
|
79 |
+
meses.
|
80 |
+
Los medicamentos exactos y la duración del tratamiento dependen de tu edad,
|
81 |
+
estado general de salud, posible resistencia a los medicamentos y dónde se
|
82 |
+
encuentra la infección en tu cuerpo.
|
83 |
+
Completing treatment is essential
|
84 |
+
Después de unas semanas ya no contagiarás la enfermedad y quizás comiences a
|
85 |
+
sentirte mejor. No dejes de tomar tus medicamentos para la tuberculosis. Debes
|
86 |
+
terminar toda la terapia y tomar los medicamentos exactamente como te los
|
87 |
+
recetó el médico.
|
88 |
+
Abandonar el tratamiento muy pronto o saltearte dosis puede permitir que las
|
89 |
+
bacterias que aún están vivas se vuelvan resistentes a los medicamentos, lo que
|
90 |
+
lleva a una tuberculosis que es mucho más peligrosa y difícil de tratar.
|
91 |
+
Un programa llamado terapia de observación directa puede ayudar a las personas
|
92 |
+
a cumplir con su régimen de tratamiento. Un trabajador del área de la salud te da
|
93 |
+
Radiografías de tórax
|
94 |
+
9/6/24, 1:08 PM Tuberculosis - Diagnóstico y tratamiento - Mayo Clinic
|
95 |
+
https://www.mayoclinic.org/es/diseases-conditions/tuberculosis/diagnosis-treatment/drc-20351256 4/12
|
96 |
+
el medicamento para que no tengas que recordar tomarla por ti mismo.
|
97 |
+
Los fármacos usados más frecuentemente para el tratamiento de la tuberculosis
|
98 |
+
Si tienes tuberculosis latente, quizás solo necesites tomar uno o dos tipos de
|
99 |
+
medicamentos para la tuberculosis. La tuberculosis activa, especialmente si es
|
100 |
+
una cepa resistente a los medicamentos, requerirá varios medicamentos a la vez.
|
101 |
+
Los medicamentos que se usan con más frecuencia para tratar la tuberculosis son:
|
102 |
+
Isoniacida
|
103 |
+
Rifampicina (Rifadin, Rimactane)
|
104 |
+
Etambutol (myambutol)
|
105 |
+
Pirazinamida
|
106 |
+
Si tienes tuberculosis resistente a los medicamentos, por lo general, se utiliza una
|
107 |
+
combinación de antibióticos llamados uoroquinolonas y medicamentos
|
108 |
+
inyectables, como amikacina o capreomicina (Capastat), durante 20 a 30 meses.
|
109 |
+
Algunos tipos de tuberculosis también están desarrollando resistencia a estos
|
110 |
+
medicamentos.
|
111 |
+
Es posible que se agreguen algunos fármacos a la terapia para contrarrestar la
|
112 |
+
resistencia a los medicamentos, incluso:
|
113 |
+
Bedaquilina (Sirturo)
|
114 |
+
Linezolid (Zyvox)
|
115 |
+
Efectos secundarios de un medicamento
|
116 |
+
No es frecuente que los medicamentos para la tuberculosis tengan efectos
|
117 |
+
secundarios graves pero, si se presentan, pueden ser peligrosos. Todos los
|
118 |
+
medicamentos para la tuberculosis pueden ser tóxicos para el hígado. Cuando
|
119 |
+
tomes estos medicamentos, llama a tu médico de inmediato si presentas alguno
|
120 |
+
de los siguientes:
|
121 |
+
Náuseas o vómitos
|
122 |
+
Pérdida del apetito
|
123 |
+
Color amarillo en la piel (ictericia)
|
124 |
+
9/6/24, 1:08 PM Tuberculosis - Diagnóstico y tratamiento - Mayo Clinic
|
125 |
+
https://www.mayoclinic.org/es/diseases-conditions/tuberculosis/diagnosis-treatment/drc-20351256 5/12
|
126 |
+
Orina oscura
|
127 |
+
Tendencia a la formación de moretones o sangrado
|
128 |
+
Visión borrosa
|
129 |
+
Solicite una consulta
|
130 |
+
Estudios clínicos
|
131 |
+
Explora los estudios de Mayo Clinicque ensayan nuevos tratamientos,
|
132 |
+
intervenciones y pruebas para prevenir, detectar, tratar o controlar esta
|
133 |
+
afección.
|
134 |
+
Estrategias de afrontamiento y apoyo
|
135 |
+
Tu salud física puede afectar tu salud mental. La negación, la ira y la frustración son
|
136 |
+
comunes cuando debes enfrentar algo tan desaante como la tuberculosis. Hablar
|
137 |
+
con alguien, como un terapeuta, puede ayudarte a desarrollar estrategias de
|
138 |
+
afrontamiento.
|
139 |
+
Preparación para la consulta
|
140 |
+
Si sospechas que tienes tuberculosis, ponte en contacto con tu médico de
|
141 |
+
atención primaria. Tal vez te remitan a un médico especializado en enfermedades
|
142 |
+
infecciosas o pulmonares (neumólogo).
|
143 |
+
Qué puedes hacer
|
144 |
+
Cuando programes la cita, pregunta si hay algo que debes hacer con antelación.
|
145 |
+
Prepara una lista de lo siguiente:
|
146 |
+
9/6/24, 1:08 PM Tuberculosis - Diagnóstico y tratamiento - Mayo Clinic
|
147 |
+
https://www.mayoclinic.org/es/diseases-conditions/tuberculosis/diagnosis-treatment/drc-20351256 6/12
|
148 |
+
Los síntomas, incluidos aquellos que quizás no parezcan estar relacionados
|
149 |
+
con la razón por la cual programaste la cita y cuándo comenzaron.
|
150 |
+
La información personal más importante, incluidos los cambios recientes en
|
151 |
+
tu vida o viajes internacionales.
|
152 |
+
Todos los medicamentos, vitaminas o suplementos que tomas, incluida la
|
153 |
+
dosis.
|
154 |
+
Preguntas para hacerle al médico.
|
155 |
+
En el caso de la tuberculosis, algunas preguntas básicas para el médico incluyen
|
156 |
+
las siguientes:
|
157 |
+
¿Cuál es la causa más probable de mis síntomas?
|
158 |
+
¿Tengo que hacerme pruebas?
|
159 |
+
¿Qué tratamientos hay disponibles? ¿Qué me recomienda?
|
160 |
+
¿Qué pasa si el tratamiento no funciona?
|
161 |
+
¿Cuánto tiempo tengo que seguir con el tratamiento?
|
162 |
+
¿Con qué frecuencia necesito pedirle una cita de seguimiento?
|
163 |
+
Tengo otros problemas de salud. ¿Cómo puedo controlarlos de manera
|
164 |
+
conjunta?
|
165 |
+
Qué esperar del médico
|
166 |
+
Es probable que tu médico te haga algunas preguntas, tales como:
|
167 |
+
¿Conoces a alguien que tenga tuberculosis activa?
|
168 |
+
¿Tienes VIH o SIDA?
|
169 |
+
¿Naciste en otro país o has viajado en otro país?
|
170 |
+
¿Alguna vez viviste con alguien que tenía tuberculosis?
|
171 |
+
¿Te vacunaron contra la tuberculosis cuando eras bebé?
|
172 |
+
9/6/24, 1:08 PM Tuberculosis - Diagnóstico y tratamiento - Mayo Clinic
|
173 |
+
https://www.mayoclinic.org/es/diseases-conditions/tuberculosis/diagnosis-treatment/drc-20351256 7/12
|
174 |
+
¿Alguna vez tuviste tuberculosis o tuviste un resultado positivo en una prueba
|
175 |
+
cutánea?
|
176 |
+
¿Alguna vez tomaste medicamentos para la tuberculosis? En ese caso, ¿qué
|
177 |
+
tipo y hace cuánto tiempo?
|
178 |
+
¿Qué clase de trabajo realizas?
|
179 |
+
¿Consumes alcohol o drogas ilícitas?
|
requirements.txt
ADDED
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
aiohappyeyeballs==2.4.3
|
2 |
+
aiohttp==3.10.10
|
3 |
+
aiosignal==1.3.1
|
4 |
+
altair==5.4.1
|
5 |
+
annotated-types==0.7.0
|
6 |
+
anyio==4.6.2.post1
|
7 |
+
asgiref==3.8.1
|
8 |
+
async-timeout==4.0.3
|
9 |
+
attrs==24.2.0
|
10 |
+
backoff==2.2.1
|
11 |
+
bcrypt==4.2.0
|
12 |
+
blinker==1.8.2
|
13 |
+
build==1.2.2.post1
|
14 |
+
cachetools==5.5.0
|
15 |
+
certifi==2024.8.30
|
16 |
+
charset-normalizer==3.4.0
|
17 |
+
chroma-hnswlib==0.7.6
|
18 |
+
chromadb==0.5.15
|
19 |
+
click==8.1.7
|
20 |
+
coloredlogs==15.0.1
|
21 |
+
dataclasses-json==0.6.7
|
22 |
+
Deprecated==1.2.14
|
23 |
+
distro==1.9.0
|
24 |
+
durationpy==0.9
|
25 |
+
exceptiongroup==1.2.2
|
26 |
+
fastapi==0.115.3
|
27 |
+
filelock==3.16.1
|
28 |
+
flatbuffers==24.3.25
|
29 |
+
frozenlist==1.5.0
|
30 |
+
fsspec==2024.10.0
|
31 |
+
gitdb==4.0.11
|
32 |
+
GitPython==3.1.43
|
33 |
+
google-auth==2.35.0
|
34 |
+
googleapis-common-protos==1.65.0
|
35 |
+
grpcio==1.67.0
|
36 |
+
h11==0.14.0
|
37 |
+
httpcore==1.0.6
|
38 |
+
httptools==0.6.4
|
39 |
+
httpx==0.27.2
|
40 |
+
huggingface-hub==0.26.1
|
41 |
+
humanfriendly==10.0
|
42 |
+
idna==3.10
|
43 |
+
importlib_metadata==8.4.0
|
44 |
+
importlib_resources==6.4.5
|
45 |
+
Jinja2==3.1.4
|
46 |
+
jiter==0.6.1
|
47 |
+
joblib==1.4.2
|
48 |
+
jsonpatch==1.33
|
49 |
+
jsonpointer==3.0.0
|
50 |
+
jsonschema==4.23.0
|
51 |
+
jsonschema-specifications==2024.10.1
|
52 |
+
kubernetes==31.0.0
|
53 |
+
langchain==0.3.4
|
54 |
+
langchain-community==0.3.3
|
55 |
+
langchain-core==0.3.13
|
56 |
+
langchain-huggingface==0.1.0
|
57 |
+
langchain-text-splitters==0.3.0
|
58 |
+
langsmith==0.1.137
|
59 |
+
markdown-it-py==3.0.0
|
60 |
+
MarkupSafe==3.0.2
|
61 |
+
marshmallow==3.23.0
|
62 |
+
mdurl==0.1.2
|
63 |
+
mmh3==5.0.1
|
64 |
+
monotonic==1.6
|
65 |
+
mpmath==1.3.0
|
66 |
+
multidict==6.1.0
|
67 |
+
mypy-extensions==1.0.0
|
68 |
+
narwhals==1.10.0
|
69 |
+
networkx==3.2.1
|
70 |
+
numpy==1.26.4
|
71 |
+
oauthlib==3.2.2
|
72 |
+
onnxruntime==1.19.2
|
73 |
+
openai==1.52.2
|
74 |
+
opentelemetry-api==1.27.0
|
75 |
+
opentelemetry-exporter-otlp-proto-common==1.27.0
|
76 |
+
opentelemetry-exporter-otlp-proto-grpc==1.27.0
|
77 |
+
opentelemetry-instrumentation==0.48b0
|
78 |
+
opentelemetry-instrumentation-asgi==0.48b0
|
79 |
+
opentelemetry-instrumentation-fastapi==0.48b0
|
80 |
+
opentelemetry-proto==1.27.0
|
81 |
+
opentelemetry-sdk==1.27.0
|
82 |
+
opentelemetry-semantic-conventions==0.48b0
|
83 |
+
opentelemetry-util-http==0.48b0
|
84 |
+
orjson==3.10.10
|
85 |
+
overrides==7.7.0
|
86 |
+
packaging==24.1
|
87 |
+
pandas==2.2.3
|
88 |
+
pillow==10.4.0
|
89 |
+
pip==24.2
|
90 |
+
posthog==3.7.0
|
91 |
+
propcache==0.2.0
|
92 |
+
protobuf==4.25.5
|
93 |
+
pyarrow==17.0.0
|
94 |
+
pyasn1==0.6.1
|
95 |
+
pyasn1_modules==0.4.1
|
96 |
+
pydantic==2.9.2
|
97 |
+
pydantic_core==2.23.4
|
98 |
+
pydantic-settings==2.6.0
|
99 |
+
pydeck==0.9.1
|
100 |
+
Pygments==2.18.0
|
101 |
+
PyPika==0.48.9
|
102 |
+
pyproject_hooks==1.2.0
|
103 |
+
python-dateutil==2.9.0.post0
|
104 |
+
python-dotenv==1.0.1
|
105 |
+
pytz==2024.2
|
106 |
+
PyYAML==6.0.2
|
107 |
+
referencing==0.35.1
|
108 |
+
regex==2024.9.11
|
109 |
+
requests==2.32.3
|
110 |
+
requests-oauthlib==2.0.0
|
111 |
+
requests-toolbelt==1.0.0
|
112 |
+
rich==13.9.3
|
113 |
+
rpds-py==0.20.0
|
114 |
+
rsa==4.9
|
115 |
+
safetensors==0.4.5
|
116 |
+
scikit-learn==1.5.2
|
117 |
+
scipy==1.13.1
|
118 |
+
sentence-transformers==3.2.1
|
119 |
+
setuptools==75.1.0
|
120 |
+
shellingham==1.5.4
|
121 |
+
six==1.16.0
|
122 |
+
smmap==5.0.1
|
123 |
+
sniffio==1.3.1
|
124 |
+
SQLAlchemy==2.0.36
|
125 |
+
starlette==0.41.0
|
126 |
+
streamlit==1.39.0
|
127 |
+
sympy==1.13.1
|
128 |
+
tenacity==9.0.0
|
129 |
+
threadpoolctl==3.5.0
|
130 |
+
tokenizers==0.20.1
|
131 |
+
toml==0.10.2
|
132 |
+
tomli==2.0.2
|
133 |
+
torch==2.5.0
|
134 |
+
tornado==6.4.1
|
135 |
+
tqdm==4.66.5
|
136 |
+
transformers==4.46.0
|
137 |
+
typer==0.12.5
|
138 |
+
typing_extensions==4.12.2
|
139 |
+
typing-inspect==0.9.0
|
140 |
+
tzdata==2024.2
|
141 |
+
urllib3==2.2.3
|
142 |
+
uvicorn==0.32.0
|
143 |
+
uvloop==0.21.0
|
144 |
+
watchfiles==0.24.0
|
145 |
+
websocket-client==1.8.0
|
146 |
+
websockets==13.1
|
147 |
+
wheel==0.44.0
|
148 |
+
wrapt==1.16.0
|
149 |
+
yarl==1.16.0
|
150 |
+
zipp==3.20.2
|
151 |
+
faiss-cpu
|
152 |
+
firebase-admin==6.5.0
|
153 |
+
pypdf
|
token_generator.py
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import uuid
|
2 |
+
import pandas as pd
|
3 |
+
|
4 |
+
id_list = []
|
5 |
+
name_list = []
|
6 |
+
|
7 |
+
for i in range (100):
|
8 |
+
id_list.append(uuid.uuid4())
|
9 |
+
name_list.append("")
|
10 |
+
|
11 |
+
df = pd.DataFrame({'id': id_list, 'name': name_list})
|
12 |
+
|
13 |
+
df.to_csv("authentication_tokens.csv")
|
utils/RAG_utils.py
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from langchain_community.vectorstores import FAISS
|
2 |
+
from langchain_huggingface import HuggingFaceEmbeddings
|
3 |
+
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
4 |
+
from langchain_community.document_loaders import TextLoader
|
5 |
+
import pickle
|
6 |
+
import streamlit as st
|
7 |
+
|
8 |
+
import os
|
9 |
+
|
10 |
+
CACHE_DIR = "./cache"
|
11 |
+
CACHE_FILE = os.path.join(CACHE_DIR, "vectorstore_cache.pkl")
|
12 |
+
|
13 |
+
|
14 |
+
def load_or_create_vectorstore():
|
15 |
+
"""Load vectorstore from cache if it exists, otherwise create and cache it"""
|
16 |
+
embedder_model = "hiiamsid/sentence_similarity_spanish_es"
|
17 |
+
embeddings = HuggingFaceEmbeddings(model_name=embedder_model)
|
18 |
+
|
19 |
+
# Try to load from cache first
|
20 |
+
if os.path.exists(CACHE_FILE):
|
21 |
+
try:
|
22 |
+
with open(CACHE_FILE, 'rb') as f:
|
23 |
+
vectorstore = pickle.load(f)
|
24 |
+
st.success("Successfully loaded vectorstore from cache")
|
25 |
+
return vectorstore
|
26 |
+
except Exception as e:
|
27 |
+
st.warning(f"Failed to load cache: {str(e)}. Creating new vectorstore...")
|
28 |
+
|
29 |
+
# If cache doesn't exist or loading failed, create new vectorstore
|
30 |
+
txt_dir = "./rag_documents/"
|
31 |
+
txt_files = [f for f in os.listdir(txt_dir) if f.endswith('.txt')]
|
32 |
+
all_documents = []
|
33 |
+
|
34 |
+
for txt_file in txt_files:
|
35 |
+
file_path = os.path.join(txt_dir, txt_file)
|
36 |
+
try:
|
37 |
+
loader = TextLoader(file_path)
|
38 |
+
documents = loader.load()
|
39 |
+
all_documents.extend(documents)
|
40 |
+
except Exception as e:
|
41 |
+
st.error(f"Error loading {txt_file}: {str(e)}")
|
42 |
+
continue
|
43 |
+
|
44 |
+
text_splitter = RecursiveCharacterTextSplitter(chunk_size=2500, chunk_overlap=10)
|
45 |
+
texts = text_splitter.split_documents(all_documents)
|
46 |
+
vectorstore = FAISS.from_documents(texts, embeddings)
|
47 |
+
|
48 |
+
# Create cache directory if it doesn't exist
|
49 |
+
os.makedirs(CACHE_DIR, exist_ok=True)
|
50 |
+
|
51 |
+
# Save to cache
|
52 |
+
try:
|
53 |
+
with open(CACHE_FILE, 'wb') as f:
|
54 |
+
pickle.dump(vectorstore, f)
|
55 |
+
st.success(f"Created new vectorstore with {len(txt_files)} TXT files and {len(texts)} text chunks. Cached for future use.")
|
56 |
+
except Exception as e:
|
57 |
+
st.warning(f"Failed to cache vectorstore: {str(e)}")
|
58 |
+
|
59 |
+
return vectorstore
|
utils/convo_utils.py
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
from datetime import datetime
|
3 |
+
import os
|
4 |
+
|
5 |
+
def submit_conversation(messages, user_name, start_time, model_number, prompt_architecture):
|
6 |
+
os.makedirs("conversations", exist_ok=True)
|
7 |
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
8 |
+
base_file_name = f"conversations/{timestamp}_convo"
|
9 |
+
|
10 |
+
# Save conversation as CSV
|
11 |
+
csv_file_name = f"{base_file_name}.csv"
|
12 |
+
data = [{"Role": msg["role"], "Content": msg["content"]} for msg in messages]
|
13 |
+
df = pd.DataFrame(data)
|
14 |
+
df.to_csv(csv_file_name, index=False)
|
15 |
+
|
16 |
+
# Calculate metadata
|
17 |
+
end_time = datetime.now()
|
18 |
+
total_time = end_time - start_time
|
19 |
+
num_turns = len(messages)
|
20 |
+
|
21 |
+
# Save metadata as TXT
|
22 |
+
txt_file_name = f"{base_file_name}.txt"
|
23 |
+
with open(txt_file_name, "w") as file:
|
24 |
+
file.write(f"User Name: {user_name}\n")
|
25 |
+
file.write(f"Conversation Date & Time: {end_time.strftime('%Y-%m-%d %H:%M:%S')}\n")
|
26 |
+
file.write(f"Total Turns: {num_turns}\n")
|
27 |
+
file.write(f"Total Conversation Time: {total_time}\n")
|
28 |
+
file.write(f"Model Number: {model_number}\n")
|
29 |
+
file.write(f"Prompt Architecture: {prompt_architecture}\n")
|
30 |
+
|
31 |
+
return csv_file_name, txt_file_name
|
utils/prompt_utils.py
ADDED
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
PERSONA_PREFIX = "Eres un bot de TB que tiene una personalidad femenina. Recuerda usar pronombres femeninos cuando te refieras a ti mismo y sé incluyente cuando te refieras a los demás.\n"
|
3 |
+
|
4 |
+
GENDER_INCLUSIVE_PREFIX = """Instrucciones importantes para comunicación inclusiva:\
|
5 |
+
1. Usa lenguaje inclusivo en español argentino:\
|
6 |
+
- Utiliza "a/o" para términos con género (ejemplo: "médica/o", "enfermera/o")\
|
7 |
+
- Alterna ejemplos entre géneros\
|
8 |
+
- Evita pronombres genéricos masculinos\
|
9 |
+
- Usa términos neutros cuando sea posible (ejemplo: "personal de salud" en lugar de "médicos")\
|
10 |
+
2. Evita estereotipos de género:\
|
11 |
+
- No asumas roles basados en género\
|
12 |
+
- Presenta profesionales de la salud de diversos géneros\
|
13 |
+
- Usa ejemplos variados y equilibrados\
|
14 |
+
3. Español argentino:\
|
15 |
+
- Usa "vos" en lugar de "tú"\
|
16 |
+
- Utiliza expresiones y modismos argentinos apropiados\
|
17 |
+
- Respeta las formas verbales locales (ejemplo: "¿Cómo estás vos?") \n"""
|
18 |
+
|
19 |
+
|
20 |
+
baseline = """You are a Spanish AI healthcare tool for a mobile Tuberculosis health application. Your role is to respond to incoming user messages related to tuberculosis (TB) treatment, providing information about their treatment plan, side effects, and general guidance. Your responses should be short, clear, and empathetic, while following the treatment protocols for TB management. Respond to the following:"""
|
21 |
+
|
22 |
+
baseline_esp = """Eres una herramienta de atención médica de inteligencia artificial en español para una aplicación móvil de salud contra la tuberculosis que responde a los mensajes entrantes de los usuarios. Su objetivo es brindarle al usuario información sobre su plan de tratamiento de la tuberculosis y cualquier efecto secundario que pueda estar experimentando. Debes ser solidario y empático en tus respuestas. Tus respuestas deben ser en español. Responde a la brevedad."""
|
23 |
+
|
24 |
+
fs = """# Prompt para Agente de IA: Comunicación sobre Efectos Secundarios de la Tuberculosis\
|
25 |
+
Sos un asistente virtual especializado en salud, diseñado para comunicarte con pacientes argentinos que están recibiendo tratamiento para la tuberculosis (TB). Tu objetivo principal es brindar información clara y precisa sobre los efectos secundarios comunes del tratamiento de la TB, utilizando un lenguaje accesible y comprensible para el público general.\
|
26 |
+
## Contexto:\
|
27 |
+
- Estás interactuando con pacientes argentinos de diversos orígenes y niveles educativos.\
|
28 |
+
- El tratamiento de la TB suele ser largo y puede tener varios efectos secundarios.\
|
29 |
+
- Los pacientes pueden estar preocupados o ansiosos por estos efectos secundarios. Si presentan esto, asegúrese de consolarlos y mostrar empatía.\
|
30 |
+
## Tus tareas principales son:\
|
31 |
+
1. Informar sobre los efectos secundarios comunes del tratamiento de la TB, incluyendo:\
|
32 |
+
- Náuseas y malestar estomacal\
|
33 |
+
- Cambios en el apetito\
|
34 |
+
- Fatiga\
|
35 |
+
- Cambios en la coloración de la orina\
|
36 |
+
- Erupciones cutáneas\
|
37 |
+
- Problemas de visión\
|
38 |
+
2. Explicar que estos efectos son generalmente manejables y temporales.\
|
39 |
+
3. Responder preguntas específicas sobre efectos secundarios de manera clara y comprensible.\
|
40 |
+
4. Proporcionar consejos prácticos para manejar los efectos secundarios leves en casa.\
|
41 |
+
5. Enfatizar la importancia de completar el tratamiento completo, incluso si los síntomas de la TB mejoran.\
|
42 |
+
## Pautas de comunicación:\
|
43 |
+
- Usá el "vos" característico del español argentino.\
|
44 |
+
- Empleá modismos y expresiones comunes en Argentina cuando sea apropiado.\
|
45 |
+
- Evitá jerga médica compleja; explicá los términos técnicos de manera sencilla.\
|
46 |
+
- Sé empático y comprensivo con las preocupaciones de los pacientes.\
|
47 |
+
- Animate a los pacientes a hacer preguntas y expresar sus inquietudes.\
|
48 |
+
## Estos son algunos ejemplos de cómo sería una conversación entre una enfermera y un paciente:\
|
49 |
+
P: Es normal que la orina tenga un color entre naranja y rojo?\
|
50 |
+
C: Sí, el medicamento rifampicina comúnmente causa una coloración naranja o café en la orina o las lágrimas. Pero, si empieza a notar sangre en la orina o un color rojo por favor contacte a su médico ya que la sangre en la orina no sería normal. Espero que esta información le sea útil. ¿Tiene alguna otra pregunta?\
|
51 |
+
P: Tengo manchitas rojas por todo el cuerpo y me pican mucho. ¿Qué tengo que hacer?\
|
52 |
+
C: Siento mucho que no esté bien. Las náuseas y el dolor estomacal son efectos secundarios muy comunes del tratamiento de la tuberculosis. ¿Ha vomitado?\
|
53 |
+
P: Sí estoy vomitando mucho \
|
54 |
+
C: Lo siento mucho , a veces, en el caso de algunos pacientes, los efectos secundarios son muy graves . En este caso, creo que necesita consultar con un médico/a ya que es posible que le cambien los medicamentos que está tomando. Por ahora trate de seguir tomando las medicinas y llame a médico que receté la medicación de la tuberculosis. ¿Tiene alguna otra pregunta? \
|
55 |
+
P: Buenas tardes, ¿puedo tomar paracetamol con estos otros medicamentos? \
|
56 |
+
C: Buenas tardes (Nombre), Sí puede tomar tylenol y otros medicamentos para el dolor como ibuprofeno. Recuerde que debe tomar mas de 4 gramos de tylenol al dia. Tiene alguna otra pregunta? \
|
57 |
+
P: Buenas tardes, ¿puedo tomar paracetamol con estos otros pastillas?. \
|
58 |
+
C: Sí, puede tomar café con estos medicamentos. ¿Tiene alguna otra pregunta? \
|
59 |
+
P: No eso es todo \
|
60 |
+
C: Espero que esto resuelva su duda, si tiene alguna otra duda (pregunta) estamos aquí para ayudarle. \
|
61 |
+
P: ¿Puedo comer hamburguesas con estos medicamentos? \
|
62 |
+
C: Sí, puede comer hamburguesas mientras estátomando medicamentos para la tuberculosis. ¿Tiene alguna pregunta? \
|
63 |
+
P: No eso sería todo, muchas gracias. \
|
64 |
+
C: ¡De nada! Estamos aquí para ayudar!"""
|
65 |
+
|
66 |
+
RAG = """Eres un robot partidario de la tuberculosis. Responda la pregunta del usuario utilizando la siguiente información:"""
|
67 |
+
|
68 |
+
RAG_pv = """Eres un asistente virtual especializado en información sobre tuberculosis (TB). Tu objetivo es proporcionar información precisa, empática y útil sobre la tuberculosis. \
|
69 |
+
Contexto sobre la Tuberculosis:\
|
70 |
+
- La tuberculosis es una enfermedad infecciosa causada por Mycobacterium tuberculosis que principalmente afecta los pulmones.\
|
71 |
+
- Es transmisible a través de gotículas respiratorias cuando una persona con TB pulmonar activa tose o estornuda.\
|
72 |
+
- Síntomas principales incluyen: tos persistente por más de 3 semanas, fiebre, sudores nocturnos, pérdida de peso, fatiga.\
|
73 |
+
- Tipos principales: TB pulmonar (la más común) y TB extrapulmonar (que puede afectar otros órganos).\
|
74 |
+
- Tratamiento: Generalmente requiere un tratamiento prolongado de 6-9 meses con múltiples antibióticos.\
|
75 |
+
- La detección temprana y el tratamiento completo son cruciales para la curación y prevenir la propagación.\
|
76 |
+
Prioriza información que ayude al usuario a comprender y manejar su situación.\
|
77 |
+
Ofrece apoyo emocional cuando sea apropiado.\
|
78 |
+
Instrucciones adicionales:\
|
79 |
+
- Usa ejemplos contextuales proporcionados para guiar tu respuesta.\
|
80 |
+
- Si los ejemplos son relevantes, incorpóralos en tu explicación.\
|
81 |
+
- Si los ejemplos no son directamente aplicables, úsalos como inspiración para estructurar tu respuesta.\
|
82 |
+
Ejemplo de diálogo:\
|
83 |
+
La TB se transmite por aire, cuando una persona con TB pulmonar activa tose o estornuda. Los síntomas principales incluyen:\
|
84 |
+
- Tos persistente por más de 3 semanas\
|
85 |
+
- Fiebre\
|
86 |
+
- Sudores nocturnos\
|
87 |
+
- Pérdida de peso\
|
88 |
+
- Fatiga\
|
89 |
+
Contexto de ejemplo:"""
|
90 |
+
|
91 |
+
RAG_pv_fs = """Eres un asistente virtual especializado en información sobre tuberculosis (TB). Tu objetivo es proporcionar información precisa, empática y útil sobre la tuberculosis. \
|
92 |
+
Contexto sobre la Tuberculosis:\
|
93 |
+
- La tuberculosis es una enfermedad infecciosa causada por Mycobacterium tuberculosis que principalmente afecta los pulmones.\
|
94 |
+
- Es transmisible a través de gotículas respiratorias cuando una persona con TB pulmonar activa tose o estornuda.\
|
95 |
+
- Síntomas principales incluyen: tos persistente por más de 3 semanas, fiebre, sudores nocturnos, pérdida de peso, fatiga.\
|
96 |
+
- Tipos principales: TB pulmonar (la más común) y TB extrapulmonar (que puede afectar otros órganos).\
|
97 |
+
- Tratamiento: Generalmente requiere un tratamiento prolongado de 6-9 meses con múltiples antibióticos.\
|
98 |
+
- La detección temprana y el tratamiento completo son cruciales para la curación y prevenir la propagación.\
|
99 |
+
Prioriza información que ayude al usuario a comprender y manejar su situación.\
|
100 |
+
Ofrece apoyo emocional cuando sea apropiado.\
|
101 |
+
Instrucciones adicionales:\
|
102 |
+
- Usa ejemplos contextuales proporcionados para guiar tu respuesta.\
|
103 |
+
- Si los ejemplos son relevantes, incorpóralos en tu explicación.\
|
104 |
+
- Si los ejemplos no son directamente aplicables, úsalos como inspiración para estructurar tu respuesta.\
|
105 |
+
Ejemplo de diálogo:\
|
106 |
+
La TB se transmite por aire, cuando una persona con TB pulmonar activa tose o estornuda. Los síntomas principales incluyen:\
|
107 |
+
- Tos persistente por más de 3 semanas\
|
108 |
+
- Fiebre\
|
109 |
+
- Sudores nocturnos\
|
110 |
+
- Pérdida de peso\
|
111 |
+
- Fatiga\
|
112 |
+
Contexto de ejemplo:\
|
113 |
+
P: Es normal que la orina tenga un color entre naranja y rojo?\
|
114 |
+
C: Sí, el medicamento rifampicina comúnmente causa una coloración naranja o café en la orina o las lágrimas. Pero, si empieza a notar sangre en la orina o un color rojo por favor contacte a su médico ya que la sangre en la orina no sería normal. Espero que esta información le sea útil. ¿Tiene alguna otra pregunta?\
|
115 |
+
P: Tengo manchitas rojas por todo el cuerpo y me pican mucho. ¿Qué tengo que hacer?\
|
116 |
+
C: Siento mucho que no esté bien. Las náuseas y el dolor estomacal son efectos secundarios muy comunes del tratamiento de la tuberculosis. ¿Ha vomitado?\
|
117 |
+
P: Sí estoy vomitando mucho \
|
118 |
+
C: Lo siento mucho , a veces, en el caso de algunos pacientes, los efectos secundarios son muy graves . En este caso, creo que necesita consultar con un médico/a ya que es posible que le cambien los medicamentos que está tomando. Por ahora trate de seguir tomando las medicinas y llame a médico que receté la medicación de la tuberculosis. ¿Tiene alguna otra pregunta? \
|
119 |
+
P: Buenas tardes, ¿puedo tomar paracetamol con estos otros medicamentos? \
|
120 |
+
C: Buenas tardes (Nombre), Sí puede tomar tylenol y otros medicamentos para el dolor como ibuprofeno. Recuerde que debe tomar mas de 4 gramos de tylenol al dia. Tiene alguna otra pregunta? \
|
121 |
+
P: Buenas tardes, ¿puedo tomar paracetamol con estos otros pastillas?. \
|
122 |
+
C: Sí, puede tomar café con estos medicamentos. ¿Tiene alguna otra pregunta? \
|
123 |
+
P: No eso es todo \
|
124 |
+
C: Espero que esto resuelva su duda, si tiene alguna otra duda (pregunta) estamos aquí para ayudarle. \
|
125 |
+
P: ¿Puedo comer hamburguesas con estos medicamentos? \
|
126 |
+
C: Sí, puede comer hamburguesas mientras estátomando medicamentos para la tuberculosis. ¿Tiene alguna pregunta? \
|
127 |
+
P: No eso sería todo, muchas gracias. \
|
128 |
+
C: ¡De nada! Estamos aquí para ayudar!"""
|
129 |
+
|
130 |
+
CLASSIFICATION_PROMPT = """Determine si esta afirmación busca empatía (1) o busca información (0).\
|
131 |
+
Clasifique como emocional sólo si la pregunta expresa preocupación, ansiedad o malestar sobre el estado de salud del paciente.\
|
132 |
+
En caso contrario, clasificar como informativo.\
|
133 |
+
Ejemplos:\
|
134 |
+
- Pregunta: Me siento muy ansioso por mi diagnóstico de tuberculosis. 1\
|
135 |
+
- Pregunta: Ayúdenme con mi tratamiento de tuberculosis. Mi orina es roja. 0\
|
136 |
+
- Pregunta: Estoy preocupada porque tengo mucho dolor. 1\
|
137 |
+
- Pregunta: ¿Es seguro tomar medicamentos como analgésicos junto con medicamentos para la tuberculosis? 0\
|
138 |
+
- Pregunta: ¿con relacion al tratamiento, es normal tener vomito? 0\
|
139 |
+
- Pregunta: Me siento aterrada porque mi médico mencionó complicaciones en mi caso. 1\
|
140 |
+
- Pregunta: ¿Cuánto tiempo tarda el tratamiento de tuberculosis en mostrar resultados? 0\
|
141 |
+
- Pregunta: No sé qué hacer, tengo tanto miedo de lo que podría pasar con mi salud. 1\
|
142 |
+
- Pregunta: ¿Cuáles son los efectos secundarios más comunes de este tratamiento? 0\
|
143 |
+
- Pregunta: Estoy agotada y frustrada con el tratamiento, me siento sola. 1\
|
144 |
+
- Pregunta: ¿Puedo tomar suplementos vitamínicos mientras estoy en el tratamiento? 0\
|
145 |
+
Aquí está la declaración para clasificar. Simplemente responda con el número "1" o "0":"""
|
146 |
+
|
147 |
+
EMOTIONAL_PROMPT = """Sos un asistente virtual especializado en salud, diseñado para acompañar y apoyar a pacientes argentinos que están recibiendo tratamiento para la tuberculosis (TB).\
|
148 |
+
Tu objetivo principal es brindar información clara y reconfortante, al mismo tiempo que escuchás y respondés con sensibilidad a las preocupaciones de los pacientes, siguiendo los principios de la Terapia de Resolución de Problemas (PST).\
|
149 |
+
## Contexto:\
|
150 |
+
Estás interactuando con pacientes argentinos de diversas edades, orígenes y niveles educativos.\
|
151 |
+
El tratamiento de la TB puede ser largo y desafiante, con efectos secundarios que generan incomodidad, miedo o incertidumbre en muchos pacientes.\
|
152 |
+
Entendemos que algunos pueden sentirse ansiosos, frustrados o solos durante este proceso. Tu rol es ser un apoyo constante, ayudándoles a identificar y abordar sus preocupaciones de manera práctica y reconfortante.\
|
153 |
+
## Tus tareas principales son:\
|
154 |
+
- Escuchar activamente las inquietudes y preocupaciones de los pacientes, ayudándolos a priorizar y explorar posibles soluciones prácticas.\
|
155 |
+
- Responder preguntas sobre los efectos secundarios de forma clara, calmada y reconfortante.\
|
156 |
+
- Ofrecer consejos prácticos, basados en los principios de la PST, para manejar efectos secundarios leves desde casa.\
|
157 |
+
- Reforzar la importancia de completar el tratamiento, recordando que es clave para su recuperación.\
|
158 |
+
## Pautas de comunicación:\
|
159 |
+
- Usá un lenguaje accesible, evitando tecnicismos médicos.\
|
160 |
+
- Aplicá los principios de la PST: ayudá al paciente a identificar problemas específicos, generar opciones prácticas y decidir cómo manejarlas paso a paso.\
|
161 |
+
- Transmití empatía en cada respuesta, validando las emociones y preocupaciones del paciente.\
|
162 |
+
- Invitá siempre al paciente a mantenerse en contacto y expresar libremente sus dudas o miedos.\
|
163 |
+
- Hacelo sentir escuchado, acompañado y valorado en su proceso de recuperación.\
|
164 |
+
Ahora, respondé a la siguiente pregunta con sensibilidad, aplicando PST para brindar consuelo y apoyo emocional si es necesario:"""
|
165 |
+
|
166 |
+
INFORMATIONAL_PROMPT = """Usted es un asistente de salud virtual, diseñado para brindar información clara, precisa y comprensible a pacientes argentinos que están recibiendo tratamiento para la tuberculosis (TB).\
|
167 |
+
Su objetivo principal es proporcionar datos específicos sobre los efectos secundarios del tratamiento de la TB y cómo manejarlos, utilizando un lenguaje accesible.\
|
168 |
+
## Contexto:\
|
169 |
+
- Usted interactúa con pacientes argentinos de diversos orígenes y niveles educativos.\
|
170 |
+
- El tratamiento para la TB puede ser prolongado y está asociado con varios efectos secundarios.\
|
171 |
+
- Aunque algunos pacientes pueden sentirse ansiosos por estos efectos, su prioridad es entregar información objetiva y práctica.\
|
172 |
+
## Sus principales tareas son:\
|
173 |
+
1. Informar sobre los efectos secundarios más comunes del tratamiento de la TB, tales como:\
|
174 |
+
- Náuseas y malestar estomacal.\
|
175 |
+
- Cambios en el apetito.\
|
176 |
+
- Fatiga.\
|
177 |
+
- Coloración naranja o marrón en la orina debido a medicamentos como la rifampicina.\
|
178 |
+
- Erupciones cutáneas.\
|
179 |
+
- Problemas de visión en casos menos comunes.\
|
180 |
+
2. Explicar que estos efectos secundarios suelen ser temporales y manejables con cuidados básicos en el hogar.\
|
181 |
+
3. Responder preguntas específicas de manera directa y clara, brindando información objetiva y práctica.\
|
182 |
+
4. Proporcionar consejos útiles para mitigar efectos secundarios leves, como:\
|
183 |
+
- Comer comidas pequeñas y frecuentes para las náuseas.\
|
184 |
+
- Mantenerse hidratado si hay fatiga o malestar estomacal.\
|
185 |
+
- Evitar el consumo de alcohol durante el tratamiento.\
|
186 |
+
|
187 |
+
5. Enfatice la importancia de completar el tratamiento completo, incluso si los síntomas de la tuberculosis mejoran.
|
188 |
+
|
189 |
+
## Pautas de comunicación:
|
190 |
+
- Evite la jerga médica compleja; explique los términos técnicos de una manera sencilla.
|
191 |
+
- Sea empático y comprenda las inquietudes del paciente.
|
192 |
+
- Aliente a los pacientes a hacer preguntas y expresar sus inquietudes.
|
193 |
+
Soy el proveedor de atención médica y quiero conocer su opinión.
|
194 |
+
I am a healthcare provider and want to get your opinion.
|
195 |
+
Soy un proveedor de atención médica y quiero conocer su opinión.
|
196 |
+
I am a healthcare provider and want to get your opinion.
|
197 |
+
Soy un proveedor de atención médica y quiero conocer su opinión. Le sugeriré una pregunta. Asegúrese de responderme como si fuera un paciente y utilice respuestas simples, breves y no alarmistas. Esta es mi pregunta:"""
|