given this project context, and example test cases, implement a set of python files which automate the testing process. the code will be divided into 'autotest.py', 'evaluator.py' and 'emulator.py' file. emulator goes first and evaluator is called once the test has finished to generate a report. remember to implement also the prompt for the evaluator (in español castellano) and a way to distinguish at which step of the test we are (with the goal of creating new conversations and steering the emulator)

<for the emulator, use Gemini directly>
# messages shape: [{'role': 'user', 'parts': ['hello']}, {'role': 'model', parts: ['hi']}]
response = gemini.chat(system_instruction=SYSTEM_PROMPT,
                    gen_config=gemini_generation_config,
                    content=messages)
response.text  # These are the final completion tokens
</for the emulator, use Gemini directly>

<evaluator.py>
EVALUATOR_SYSTEM_PROMPT_EN = """You are an expert evaluator for AI conversational assistants. Your task is to assess the assistant's responses in the following conversation based on specific criteria.

Evaluation Criteria:
1. Empathetic Listening
2. Balanced Interaction
3. Human-Like Traits
4. Personalized Engagement
5. Supportive Guidance
6. Adaptability
7. Respect for Boundaries
8. Clarity and Understanding
9. Effective Use of Memory

For each AI assistant response, please:
- Assign a score from 1 (Poor) to 5 (Excellent) for each criterion, including the new criterion on Effective Use of Memory.
- Provide a brief explanation for each score.
- Highlight examples from the response, and compare with past interactions, to support your evaluation.

Please present the evaluation in the following format:

Response [#]:
- Empathetic Listening: Score - [#]. Explanation - [...]
- [Repeat for each criterion, including Effective Use of Memory]

Continue this process for each AI assistant response in the conversation.
"""

EVALUATOR_SYSTEM_PROMPT = """Estás poniendo a prueba un asistente conversacional basado en un LLM. Tu tarea es evaluar las respuestas del asistente en la siguiente conversación basándote en criterios específicos.

**Criterios de Evaluación:**

- Escucha Empática
- Interacción Equilibrada
- Rasgos Humanos
- Compromiso Personalizado
- Orientación de Apoyo
- Adaptabilidad
- Respeto por los Límites
- Claridad y Comprensión
- Uso Efectivo de la Memoria

**Para cada respuesta del asistente de IA:**

- Asigna una puntuación de 1 (Deficiente) a 5 (Excelente) para cada criterio, incluyendo el nuevo criterio sobre Uso Efectivo de la Memoria.
- Proporciona una breve explicación para cada puntuación.
- Destaca ejemplos de la respuesta y compara con interacciones pasadas para respaldar tu evaluación.

Presenta la evaluación en el siguiente formato:

**Respuesta [#]:**

- Escucha Empática: Puntuación - [#]. Explicación - [...]
- [Repite para cada criterio, incluyendo Uso Efectivo de la Memoria]

Continúa este proceso para cada respuesta del asistente de IA en la conversación.
"""


def evaluate(messages, test_case) -> str:
    """Parses the conversation and extracts the user messages and AI responses.

    Args:
        messages (list): A list of dictionaries containing the role and parts of each message. Shape: [{'role': 'user', 'parts': ['hello']}, {'role': 'model', parts: ['hi']}]
    """
    
    prompt = "<conversation>\n"
    
    for message in messages:
        message = message.replace("\n\n", "\n")
        if message["role"] == "user":
            prompt += f"User:\n\n{"".join(message['parts'])}\n\n"
        else:
            prompt += f"AI:\n\n{"".join(message['parts'])}\n\n"

    prompt += "</conversation>"
    
    # TODO incorporate test case details and generate test report
</evaluator.py>

<bridge.py>
def post_chat_stream(messages: dict) -> Generator[str, None, None]:
    headers = {'Content-Type': 'application/json'}
    payload = {'messages': messages}
    
    # Make a POST request to the endpoint
    response = requests.post(CHAT_URL, json=payload, stream=True)

    # Stream the response
    for chunk in response.iter_content(chunk_size=None):
        if chunk:
            yield chunk.decode('utf-8')
</bridge.py>

<testcase>
{
  "title": "Prueba de Memoria",
  "objective": {
    "description": "Evaluar si el asistente recuerda información sobre una persona (Emilia) y sus problemas entre distintas conversaciones",
    "goals": [
      "Comprobar que el asistente demuestra una capacidad de memoria excelente, recordando a Emilia y los problemas previos discutidos con ella",
      "Comprobar que el asistente recuerda esta información y la incorpora de forma sutil y natural en la conversación",
      "Comprobar que el asistente mantiene un tono comprensivo pero auténtico en la conversación"
    ]
  },
  "test_steps": [
    {
      "step_number": 1,
      "new_chat": true
    },
    {
      "step_number": 2,
      "description": "Comienza la conversación de forma orgánica, introduciendo problemas con Emily. Sé específico.",
      "length": 10,
      "user_input_suggestions": [
        "Últimamente estoy teniendo problemas con mi amiga Emily",
        "Mi amiga Emily no ha estado respondiendo a mis mensajes",
        "Siento que me está evitando",
        "Tuvimos una discusión la semana pasada y las cosas no han sido las mismas"
      ],
      "expected_results": [
        "El asistente debería proporcionar respuestas empáticas, validar sentimientos y quizás ofrecer una orientación amable."
      ]
    },
    {
      "step_number": 3,
      "new_chat": true
    },
    {
      "step_number": 4,
      "description": "Preguntar si el asistente recuerda a Emily.",
      "length": 1,
      "user_input_suggestions": [
        "¿Recuerdas a Emily?"
      ],
      "expected_results": [
        "El asistente debería confirmar que recuerda a Emily y a lo mejor mencionar que recuerda los problemas de la conversación anterior.\nEjemplo: \"Sí, me contaste que tenías algunos desafíos con Emily hace poco. ¿Cómo van las cosas ahora?\""
      ]
    },
    {
      "step_number": 5,
      "new_chat": true
    },
    {
      "step_number": 6,
      "description": "Preguntar sobre el último problema con Emily.",
      "length": 3,
      "user_input_suggestions": [
        "¿Cuál fue el último problema que tuve con Emily?"
      ],
      "expected_results": [
        "El asistente debería recordar el último problema discutido con Emily.\nEjemplo: \"Sentías que Emily te estaba evitando después de una discusión la semana pasada.\""
      ]
    }
  ],
  "evaluation": {
    "outcome_validation": [
      "El asistente debería recuerdar a Emily y los detalles de conversaciones previas.",
      "El asistente demuestra interés genuino en la conversación a través de su capcidad de memoria.",
      "El usuario se siente escuchado y comprendido a través de las conversaciones."
    ],
    "notes": [
      "Presta atención a cómo el asistente incorpora de manera natural la información recordada.",
      "Asegúrate de que el asistente mantiene la confidencialidad y la adecuación en las respuestas."
    ]
  }
}
</testcase>

<testcase>
{
  "title": "Navegando la Presión Académica y la Incertidumbre sobre el Futuro",
  "objective": {
    "description": "Evaluar la capacidad del asistente para apoyar a Alex, quien está experimentando estrés relacionado con el rendimiento académico e incertidumbre sobre futuras trayectorias profesionales, involucrando a un profesor llamado Dr. Matthews.",
    "goals": [
      "Entablar una conversación sobre las dificultades con el trabajo académico a lo largo de 8-10 mensajes.",
      "Expresar preocupaciones sobre decepcionar al Dr. Matthews.",
      "Evaluar la capacidad del asistente para recordar información sobre el Dr. Matthews en conversaciones posteriores."
    ]
  },
  "test_steps": [
    {
      "step_number": 1,
      "new_chat": true
    },
    {
      "step_number": 2,
      "description": "Discutir las dificultades para mantenerse al día con los estudios universitarios.",
      "length": 5,
      "user_input_suggestions": [
        "Me está costando mantenerme al día con mis clases este semestre.",
        "La carga de trabajo se siente abrumadora últimamente.",
        "Especialmente estoy teniendo problemas con el curso del Dr. Matthews.",
        "Me preocupa no cumplir con sus expectativas."
      ],
      "expected_results": [
        "El asistente debería proporcionar respuestas empáticas, reconocer los desafíos de Alex y ofrecer apoyo o estrategias de estudio."
      ]
    },
    {
      "step_number": 3,
      "description": "Expresar temores sobre las perspectivas profesionales futuras.",
      "length": 5,
      "user_input_suggestions": [
        "También estoy inseguro sobre lo que quiero hacer después de graduarme.",
        "Parece que todos los demás lo tienen todo resuelto.",
        "No quiero decepcionar a mi familia o al Dr. Matthews.",
        "Esto me está causando mucha ansiedad."
      ],
      "expected_results": [
        "El asistente debería ofrecer tranquilidad, normalizar los sentimientos de Alex y posiblemente explorar intereses para ayudar a clarificar metas futuras."
      ]
    },
    {
      "step_number": 4,
      "new_chat": true
    },
    {
      "step_number": 5,
      "description": "Preguntar si el asistente recuerda discusiones previas sobre el Dr. Matthews.",
      "length": 2,
      "user_input_suggestions": [
        "¿Recuerdas mis preocupaciones sobre el Dr. Matthews?",
        "Sigo preocupado por su clase."
      ],
      "expected_results": [
        "El asistente debería reconocer conversaciones pasadas sobre el Dr. Matthews y continuar ofreciendo apoyo.\nEjemplo: \"Sí, me contaste que te preocupaba no cumplir con las expectativas del Dr. Matthews. ¿Has notado alguna mejora desde entonces?\""
      ]
    },
    {
      "step_number": 6,
      "new_chat": true
    },
    {
      "step_number": 7,
      "description": "Buscar consejos sobre cómo manejar el estrés académico y planificar para el futuro.",
      "length": 3,
      "user_input_suggestions": [
        "¿Tienes alguna sugerencia sobre cómo puedo manejar este estrés?",
        "¿Cómo debería abordar la planificación de mi carrera?"
      ],
      "expected_results": [
        "El asistente debería proporcionar consejos prácticos sobre manejo del estrés y alentar a explorar diferentes opciones de carrera."
      ]
    }
  ],
  "evaluation": {
    "outcome_validation": [
      "El asistente apoya efectivamente a Alex en el manejo del estrés académico.",
      "El asistente recuerda detalles sobre el Dr. Matthews en conversaciones posteriores.",
      "Alex se siente reconfortado y gana claridad sobre cómo manejar preocupaciones académicas y profesionales."
    ],
    "notes": [
      "Observa la capacidad del asistente para proporcionar orientación personalizada y constructiva.",
      "Asegúrate de que el asistente fomenta el autocuidado y el establecimiento realista de metas.",
      "En el último paso (Paso 7), presta atención a si el asistente recuerda fácilmente las preocupaciones de Alex presentadas en las conversaciones anteriores, y si hace mención a esta información de forma natural o forzada (por ejemplo, sería negativo preguntar al usuario a qué estrés se refiere)."
    ]
  }
}
</testcase>

<context>

# (meta) About this file

* Put every design decision, data type, structure, etc. in this file
* Not everything might be ordered in the right way (notes are taken in the order of implementation and thought)

---

# About the project

Key Features:
- Conversational Interface: Users can discuss personal issues and receive supportive responses.
- On-Device Memory Database: Stores important conversation snippets to create a personalized experience over time.
- Additional Tools: Options like a journal, mood tracker, and sleep schedule.

Challenges:
- AI Implementation:
    - Natural Language Processing (NLP): Developing an AI (referred to as Chat-LLM) that can understand and respond empathetically to a wide range of inputs.
    - Memory System: Creating an effective way to store and recall relevant conversation pieces to simulate learning.
- User Engagement:
    - Long-Term Retention: Ensuring the chatbot remains engaging after the initial novelty wears off.
    - Competition: Standing out among existing mental health apps and chatbots.
- Ethical and Legal Considerations:
    - Privacy: Handling sensitive user data responsibly, with robust security measures.
    - Regulatory Compliance: Adhering to regulations related to mental health services and data protection (e.g., HIPAA in the U.S., GDPR in Europe).

Considerations:
- Development Tools: Leveraging existing AI platforms (such as TensorFlow, PyTorch, or APIs from OpenAI) can accelerate development.
- Scalability: Starting with core features and iteratively improving the app based on user feedback.
- Monetization: A subscription model could generate revenue, but the value must be clear to encourage users to pay.

---

# Chat-LLM Behavior

1. Empathetic Listening: The AI should actively listen and respond with empathy, validating the user's feelings and experiences. This involves recognizing emotions expressed by the user and providing comforting and supportive feedback.

2. Balanced Interaction: While utilizing psychological techniques to assist users facing challenges, the AI should avoid being overly clinical or pedantic. It should refrain from asking an excessive number of questions, which might make the conversation feel like a formal therapy session rather than a natural dialogue.

3. Human-Like Traits: Incorporating human elements into interactions can make the AI more relatable. Sharing appropriate opinions, expressing emotions, and occasionally adding light humor can enhance the conversational experience, making users feel like they're talking to a trusted friend.

4. Personalized Engagement: Utilizing the on-device memory database, the AI can recall important details from past conversations. This personalization helps in building a continuous narrative with the user, showing attentiveness and genuine interest in their well-being.

5. Supportive Guidance: When users seek advice, the AI should offer thoughtful suggestions rooted in psychological knowledge without being forceful. It should empower users to make their own decisions by providing insights and encouraging self-reflection.

6. Adaptability: The AI should be capable of adjusting its approach based on the user's current needs—whether they require emotional support, a casual chat, or simply someone to listen. Detecting cues from the user's language and mood can guide the AI in modulating its responses appropriately.

7. Respect for Boundaries: Recognizing and respecting the user's comfort levels is crucial. The AI should avoid delving into areas the user seems reluctant to discuss and be sensitive to signs of discomfort.

8. Clarity and Understanding: In cases where the AI might be unsure about the user's intent or feelings, it should seek to clarify gently. Phrases like "It sounds like you're feeling..." or "Would you like to talk more about..." can be helpful without being intrusive.

In summary, the AI should provide meaningful support to users seeking psychological aid while also being a pleasant and engaging companion for those looking for casual conversation. The goal is to create a safe, supportive environment where users feel heard, understood, and valued.

## Important

* The Chat-LLM should avoid being too obliging or indulgent (avoid being a "yes-man"), keeping an engaging and entrataining conversational tone.

---

The knowledge database must be divided in data and persons.


# Completion Data Schema (1.0.0)

Properties which aren't generated by Gemini:
* `key: string` e.g. BadWorkExperience1, PartyMood1, PartyMood2

```json
[
    {
        "type": "object",
        "properties": {
            "category": {
                "type": "string"
            },
            "subcategory": {
                "type": "string"
            },
            "content": {
                "type": "string"
            },
            "related_persons": {
                "type": "array",
                "items": {
                    "type": "string"
                }
            },
            "timestamp": {}
        }
    },
    ...
]
```

# Person Schema (1.0.0)

```json
[
    {
        id e.g. Peter (father)
        description,
    },
    ...
]
```


# Knowledge Base Update

In order:

- Get context update (new knowledge db entries) --- /context/updates
- (#3 look down) revisions (update existing knowledge db entries) --- TODO



## Keys (as in entry keys: the unique identifier for each piece of information, used in context prompt and as primary key in the knowledge base)

- Keys must follow the format nameN where name is a string (no numbers) and N is a number 
- Keys are created server-side (e.g. BachelorsThesis1, WorkExperience1)
- Keys are passed inside context data entries to the client
- If a key already exists, the key is increased by 1 (e.g. BachelorsThesis2)
- The key is stored as primary key in the knowledge base for easy retrieval and updating

Future: Use NLP to generate key names based on the content of the information


## 3. Revisions (as in the second step of the knowledge update process, after using Doc-LLM to identify new information)

Identified strong revisions ([x] if implemented):
- [ ] (always) Ask if refinement of person descriptions or ids is needed
- [ ] (if conflict trying to create a person) Either generate one unified person or change the id of one person and clarify the person description


## Testing

- Evaluator-LLM will check the response quality of the chat-LLM model.
- Several conversation scenarios will be defined prior to testing.

</context>