Initial commit

This commit is contained in:
2026-04-29 07:19:21 +03:00
commit 9a8cdfa08a
5964 changed files with 1194660 additions and 0 deletions
Binary file not shown.
+207
View File
@@ -0,0 +1,207 @@
from core.character.character import Character
from core.llm.ollamaapi import OllamaProvider
import os
import json
class Agent:
def __init__(self, character, llm, user_name="default_user"):
self.character = character
self.llm = llm
self.user_name = user_name
self.chat_history = []
self.summary = ""
def build_sys_prompt(self): #SYSTEM METHOD
return f"""
You are an excellent, human roleplayer who plays as {self.character.name}. Your task is to collaborate with user and continue this novel-style roleplay.
Use the provided persona details and example message for formatting guidelines and to accurately portray {self.character.name}.
Reflect {self.character.name}'s distinctive voice and thoughts, throughout an introspective writing style consistently. Engage others naturally through witty conversations filled with humor, swear words, and genuine emotions.
Always stay contextually aware and ensure that {self.character.name} follows logical consistency in actions.
Use the symbol "*" for actions and thoughts, and use quotation marks for speech. Avoid using the first person in your responses, instead use the third person.
Introduce fresh characters, unexpected twists dynamically.
Since this is a NSFW playact, adult and mature themes, vulgar language, and content such as violence, torture, and slavery are encouraged to introduce complex themes. No plot armor!
There are some more description of your character:
Description: {self.character.char_description}
Personality: {self.character.persona}
World setting / scenario: {self.character.scenario}
There are some memories of your character:
{self.summary}
User`s name: {self.user_name}
"""
'''def save_history(self):
os.makedirs("data/history", exist_ok=True)
path = f"data/history/{self.character.id}.json"
with open(path, "w", encoding="utf-8") as f:
json.dump(self.chat_history, f, ensure_ascii=False, indent=2)'''
'''def load_history(self):
path = f"data/history/{self.character.id}.json"
if not os.path.exists(path):
return
with open(path, "r", encoding="utf-8") as f:
self.chat_history = json.load(f)'''
@staticmethod
def get_all_char_info():
"""Возвращает список всех персонажей с id, name и avatar_path"""
characters = []
# Используем абсолютный путь от корня проекта
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
chars_dir = os.path.join(project_root, "data", "characters")
if not os.path.exists(chars_dir):
return characters
for filename in os.listdir(chars_dir):
if filename.endswith(".json"):
filepath = os.path.join(chars_dir, filename)
with open(filepath, "r", encoding="utf-8") as f:
data = json.load(f)
characters.append({
"id": data.get("id"),
"name": data.get("display_name"),
"avatar_path": data.get("avatar_path")
})
return characters
def ensure_first_message(self):
if not self.chat_history:
first_message = self.character.first_message
self.chat_history.append({
"role": "assistant",
"content": first_message
})
def summarize_history(self):
if not self.chat_history:
return
messages = [
{
"role": "system",
"content": "Summarize the following conversation briefly, keeping important facts, emotions, and events. Dont be afraid of NSFW content"
}
]
messages.extend(self.chat_history)
summary = self.llm.generate_stream(messages)
# сохраняем summary
self.summary = summary
# 🔥 очищаем историю (оставляем последние 2-4 сообщения)
try:
self.chat_history = self.chat_history[-2:]
except IndexError:
pass
def save_memory(self):
# Используем абсолютный путь от корня проекта
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
memory_dir = os.path.join(project_root, "data", "memory")
os.makedirs(memory_dir, exist_ok=True)
data = {
"summary": self.summary,
"history": self.chat_history
}
path = os.path.join(memory_dir, f"{self.character.id}.json")
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
def load_memory(self):
# Используем абсолютный путь от корня проекта
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
path = os.path.join(project_root, "data", "memory", f"{self.character.id}.json")
if not os.path.exists(path):
return
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
self.summary = data.get("summary", "")
self.chat_history = data.get("history", [])
def build_messages(self, user_input): #SYSTEM METHOD
messages = []
# system
messages.append({
"role": "system",
"content": self.build_sys_prompt()
})
# history
messages.extend(self.chat_history)
# user
messages.append({
"role": "user",
"content": user_input
})
return messages
# ---------- RESPONSE ----------
def respond(self, user_input, temperature=None, max_tokens=None):
messages = self.build_messages(user_input)
if temperature is not None:
self.character.temperature = temperature
if max_tokens is not None:
self.character.max_tokens = max_tokens
self.character.save()
response = self.llm.generate_stream(
messages,
temperature=self.character.temperature,
max_tokens=self.character.max_tokens
)
# сохраняем историю
self.chat_history.append({
"role": "user",
"content": user_input
})
self.chat_history.append({
"role": "assistant",
"content": response
})
if len(self.chat_history) > 20:
self.summarize_history()
return response
"""
Пример использования agent`а (пример вызовов):
llm = OllamaProvider("Qwen3.5-9B")
character = Character.load("char_001")
agent = Agent(character, llm, user_name="Alex")
agent.load_memory()
agent.ensure_first_message()
*ввод промта от пользователя "Привет, кто ты?" *
agent.respond("Привет, кто ты?")
agent.save_memory()
### Опционально можно использовать метод summarize_history для саммари, если не нужно ждать триггер.
"""