File size: 7,394 Bytes
7d6d833
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
from typing import Union
from mistralai import Mistral
import yaml
from pathlib import Path
import re
import json
import time


class AIAgent:
    def __init__(
        self,
        name,
        personal_context,
        character,
        emotions,
        attitudes,
        goal,
        general_context,
        client,
        arbitrary_agent=None
    ):
        """
        Initialise l'agent IA avec ses attributs de base.

        :param name: Nom de l'agent
        :param character: dict décrivant la personnalité de l'IA
        :param emotions: dict des émotions actuelles de l'IA
        :param goal: Objectif principal de l'IA
        :param general_context: Contexte général (ex: sujet du débat)
        :param arbitrary_agent: Objet gérant la logique de mise à jour des émotions
        """
        self.client = client
        self.model = "mistral-large-latest"

        self.name = name
        self.personal_context = personal_context
        self.character = character
        self.emotions = emotions
        self.attitudes = attitudes
        self.goal = goal

        self.general_context = general_context
        self.arbitrary_agent = arbitrary_agent

        self.context_memory = ""
    
    @classmethod
    def from_yaml(cls, character_yaml: Union[Path, str], general_context_yaml:  Union[Path, str], client, arbitrary_agent=None):
        """
        Initialize an object using YAML content.
        """
        character_data = cls.parse_yaml_to_dict(str(character_yaml))
        context_data = cls.parse_yaml_to_dict(str(general_context_yaml))
        if character_data:
            return cls(
                client=client,
                name=character_data.get("name"),
                personal_context =character_data.get("personal_context"),
                character=character_data.get("character"),
                emotions=character_data.get("emotions"),
                attitudes=character_data.get("attitudes"),
                goal=character_data.get("goal"),
                general_context = context_data.get("general_context"),
                arbitrary_agent = arbitrary_agent
            )
        else:
            raise ValueError("Failed to parse YAML content.")
    
    @staticmethod
    def parse_yaml_to_dict(yaml_content):
        """
        Parse YAML content into a Python dictionary.
        """
        try:
            with open(yaml_content, 'r') as file:
                return yaml.safe_load(file)
        except FileNotFoundError:
            print(f"Error: The file '{yaml_content}' was not found.")
        except yaml.YAMLError as e:
            print(f"Error parsing YAML file: {e}")
        except Exception as e:
            print(f"Unexpected error: {e}")
        return None
    
    def __repr__(self):
        return (f"TrumpProfile(\n"
                f"  general_context={self.general_context},\n"
                f"  {self.name}_character={self.character},\n"
                f"  {self.name}_emotions={self.emotions},\n"
                f"  {self.name}_attitudes={self.attitudes},\n"
                f"  {self.name}_goal='{self.goal}'\n"
                f")")
    
    def respond(self, input_text):
        """
        Génère une réponse basée sur le contexte fourni.

        :param input_text: Texte reçu
        :param opponent_state: État actuel de l'adversaire (dict)
        :return: Réponse de l'IA
        """
        
        response = self._generate_response(
            instructions=input_text,
            environment_description="N/A"
        )
        return response

    def update_emotions(self, input_text):
        """
        Met à jour les émotions en fonction d'une analyse via l'arbitrary_agent (LLM).
        """
        self.context_memory = self.create_memory_context(input_text)

        if self.arbitrary_agent is not None:
            self.emotions, self.attitudes = self.arbitrary_agent.update_emotions(character=self)
        else:
            print("No arbitrary agent provided. Emotions remain unchanged.")

    def _generate_response(self, instructions, environment_description, max_tokens=None):
        messages = [
            {
                "role": "system",
                "content": (
                    f"General context: {self.general_context}\n"
                    #f"Personal context: {self.personal_context}\n"
                    f"Character: {self.character}\n"
                    f"Goal: {self.goal}\n"
                    f"Emotions: {self.emotions}\n"
                    f"Attitudes: {self.attitudes}\n"
                    f"Environment: {environment_description}\n"
                ),
            },
            {
                "role": "user",
                "content": (
                    f"Instructions: {instructions}\n"
                    f"Conversation history: {self.context_memory}"
                ),
            },
        ]
        # ------------------------------
        # Hypothetical call to LLM API
        # ------------------------------
        time.sleep(1)
        chat_response = self.client.chat.complete(
            model=self.model,
            messages=messages,
            max_tokens=max_tokens if max_tokens else None
        )
        # ------------------------------------------------
        return chat_response.choices[0].message.content

    def create_memory_context(
        self,
        current_input,
        additional_instructions="Summarize recent key points and emotional undertones."
    ):
        """
        Calls LLM to produce a memory context (summary, emotional tone, etc.) in valid JSON.
        """

        system_prompt = (
            "You are a memory transformation engine. "
            "Based on the agent's current input, current context memory, character personality, and current emotions, "
            "produce a concise memory context in valid JSON."
        )

        user_prompt = f"""
                        Character: {self.name}
                        Emotions: {self.emotions}
                        Current answer he get: {current_input}
                        Context memory: {self.context_memory}

                        Task:
                        - {additional_instructions}
                        - Return structured memory context in valid JSON. Example:
                        {{
                            "summary": "...",
                            "emotionalTone": "..."
                        }}
                        """

        messages = [
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": user_prompt},
        ]

        time.sleep(1)
        response = self.client.chat.complete(
            model=self.model,
            messages=messages,
            response_format={"type": "json_object"},
            max_tokens=300
        )

        raw_text = response.choices[0].message.content.strip()
        cleaned_response = re.sub(r"```(json)?", "", raw_text).strip()

        try:
            memory_context = json.loads(cleaned_response)
        except json.JSONDecodeError:
            print(f"Error: Could not parse JSON for memory context. Using fallback.\nResponse: {cleaned_response}")
            memory_context = {
                "summary": "No valid summary",
                "emotionalTone": "neutral"
            }

        return memory_context