Biasa bug yang sama berulang-ulang
This commit is contained in:
parent
fe065f74d6
commit
0fa6fc9db9
44
config.py
44
config.py
@ -44,7 +44,7 @@ AGENT_MAX_TOOL_OUTPUT = int(os.getenv("AGENT_MAX_TOOL_OUTPUT", default=_yaml_get
|
|||||||
|
|
||||||
# ─── Persona / Mode (YAML, bisa di-override dari .env) ──────────────────────────
|
# ─── Persona / Mode (YAML, bisa di-override dari .env) ──────────────────────────
|
||||||
|
|
||||||
AGENT_SKILL = os.getenv("AGENT_SKILL", default=_yaml_get("persona", "skill", default="programmer")).strip().lower()
|
AGENT_SKILL = os.getenv("AGENT_SKILL", default="programmer").strip().lower()
|
||||||
PERSONA_NAME = os.getenv("PERSONA_NAME", default=_yaml_get("persona", "name", default="Hendrik")).strip() or "Hendrik"
|
PERSONA_NAME = os.getenv("PERSONA_NAME", default=_yaml_get("persona", "name", default="Hendrik")).strip() or "Hendrik"
|
||||||
PERSONA_AGE = os.getenv("PERSONA_AGE", default=_yaml_get("persona", "age", default="")).strip()
|
PERSONA_AGE = os.getenv("PERSONA_AGE", default=_yaml_get("persona", "age", default="")).strip()
|
||||||
PERSONA_GENDER = os.getenv("PERSONA_GENDER", default=_yaml_get("persona", "gender", default="")).strip()
|
PERSONA_GENDER = os.getenv("PERSONA_GENDER", default=_yaml_get("persona", "gender", default="")).strip()
|
||||||
@ -58,8 +58,8 @@ PERSONA_CATCHPHRASES = os.getenv("PERSONA_CATCHPHRASES", default=_yaml_get("pers
|
|||||||
|
|
||||||
# ─── Character & Skills (YAML, bisa di-override dari .env) ─────────────────────
|
# ─── Character & Skills (YAML, bisa di-override dari .env) ─────────────────────
|
||||||
|
|
||||||
AGENT_CHARACTER = os.getenv("AGENT_CHARACTER", default=_yaml_get("character", "preset", default="")).strip().lower()
|
AGENT_CHARACTER = os.getenv("AGENT_CHARACTER", default=_yaml_get("agent", "character", default="")).strip().lower()
|
||||||
AGENT_SKILLS = os.getenv("AGENT_SKILLS", default=_yaml_get("character", "skills", default="")).strip().lower()
|
AGENT_SKILLS = os.getenv("AGENT_SKILLS", default="").strip().lower()
|
||||||
|
|
||||||
|
|
||||||
# ─── XMPP (non-credential dari YAML, credential dari .env) ─────────────────────
|
# ─── XMPP (non-credential dari YAML, credential dari .env) ─────────────────────
|
||||||
@ -91,8 +91,21 @@ TYPING_MAX = float(os.getenv("TYPING_MAX", default=_yaml_get("delay", "t
|
|||||||
ENV_CHARACTERS_DIR = Path(__file__).resolve().parent / "agent" / "characters"
|
ENV_CHARACTERS_DIR = Path(__file__).resolve().parent / "agent" / "characters"
|
||||||
ENV_CHARACTER_CONFIG_PATH = ENV_CHARACTERS_DIR / AGENT_CHARACTER / "character.md" if AGENT_CHARACTER else None
|
ENV_CHARACTER_CONFIG_PATH = ENV_CHARACTERS_DIR / AGENT_CHARACTER / "character.md" if AGENT_CHARACTER else None
|
||||||
|
|
||||||
if ENV_CHARACTER_CONFIG_PATH and ENV_CHARACTER_CONFIG_PATH.is_file():
|
# Coba persona.yaml dulu (prioritas utama), kalau tidak ada fallback ke character.md
|
||||||
_character_env: dict[str, str] = {}
|
_persona_yaml_path = ENV_CHARACTERS_DIR / AGENT_CHARACTER / "persona.yaml" if AGENT_CHARACTER else None
|
||||||
|
|
||||||
|
if _persona_yaml_path and _persona_yaml_path.is_file():
|
||||||
|
# Prioritas utama: baca persona.yaml dari character directory
|
||||||
|
try:
|
||||||
|
_character_env = yaml.safe_load(_persona_yaml_path.read_text(encoding="utf-8")) or {}
|
||||||
|
if not isinstance(_character_env, dict):
|
||||||
|
_character_env = {}
|
||||||
|
except Exception as _e:
|
||||||
|
print(f"[config] Warning: gagal load persona.yaml untuk '{AGENT_CHARACTER}': {_e}")
|
||||||
|
_character_env = {}
|
||||||
|
elif ENV_CHARACTER_CONFIG_PATH and ENV_CHARACTER_CONFIG_PATH.is_file():
|
||||||
|
# Fallback: baca character.md (format lama)
|
||||||
|
_character_env = {}
|
||||||
for line in ENV_CHARACTER_CONFIG_PATH.read_text(encoding="utf-8").splitlines():
|
for line in ENV_CHARACTER_CONFIG_PATH.read_text(encoding="utf-8").splitlines():
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if not line or line.startswith("#"):
|
if not line or line.startswith("#"):
|
||||||
@ -100,6 +113,10 @@ if ENV_CHARACTER_CONFIG_PATH and ENV_CHARACTER_CONFIG_PATH.is_file():
|
|||||||
if "=" in line:
|
if "=" in line:
|
||||||
key, value = line.split("=", 1)
|
key, value = line.split("=", 1)
|
||||||
_character_env[key.strip()] = value.strip()
|
_character_env[key.strip()] = value.strip()
|
||||||
|
else:
|
||||||
|
_character_env = None
|
||||||
|
|
||||||
|
if _character_env:
|
||||||
|
|
||||||
_character_overrides = {
|
_character_overrides = {
|
||||||
"AGENT_SKILL": AGENT_SKILL,
|
"AGENT_SKILL": AGENT_SKILL,
|
||||||
@ -113,8 +130,23 @@ if ENV_CHARACTER_CONFIG_PATH and ENV_CHARACTER_CONFIG_PATH.is_file():
|
|||||||
"PERSONA_MOOD": PERSONA_MOOD,
|
"PERSONA_MOOD": PERSONA_MOOD,
|
||||||
"PERSONA_CATCHPHRASES": PERSONA_CATCHPHRASES,
|
"PERSONA_CATCHPHRASES": PERSONA_CATCHPHRASES,
|
||||||
}
|
}
|
||||||
|
# Mapping dari key persona.yaml ke key config
|
||||||
|
_yaml_to_config_key = {
|
||||||
|
"AGENT_SKILL": "skill",
|
||||||
|
"PERSONA_NAME": "name",
|
||||||
|
"PERSONA_AGE": "age",
|
||||||
|
"PERSONA_GENDER": "gender",
|
||||||
|
"PERSONA_TONE": "tone",
|
||||||
|
"PERSONA_VERBOSITY": "verbosity",
|
||||||
|
"PERSONA_HUMOR": "humor",
|
||||||
|
"PERSONA_LANGUAGE": "language",
|
||||||
|
"PERSONA_MOOD": "mood",
|
||||||
|
"PERSONA_CATCHPHRASES": "catchphrases",
|
||||||
|
}
|
||||||
for key, fallback in _character_overrides.items():
|
for key, fallback in _character_overrides.items():
|
||||||
value = _character_env.get(key, fallback).strip()
|
yaml_key = _yaml_to_config_key.get(key, key.lower())
|
||||||
|
raw = _character_env.get(yaml_key, _character_env.get(key, fallback))
|
||||||
|
value = str(raw).strip() if raw is not None else ""
|
||||||
if key in {"AGENT_SKILL", "PERSONA_TONE", "PERSONA_VERBOSITY", "PERSONA_HUMOR", "PERSONA_LANGUAGE", "PERSONA_MOOD"}:
|
if key in {"AGENT_SKILL", "PERSONA_TONE", "PERSONA_VERBOSITY", "PERSONA_HUMOR", "PERSONA_LANGUAGE", "PERSONA_MOOD"}:
|
||||||
value = value.lower() or fallback
|
value = value.lower() or fallback
|
||||||
if key == "PERSONA_NAME" and not value:
|
if key == "PERSONA_NAME" and not value:
|
||||||
|
|||||||
10
config.yaml
10
config.yaml
@ -1,16 +1,10 @@
|
|||||||
agent:
|
agent:
|
||||||
max_iterations: 40
|
max_iterations: 40
|
||||||
max_tool_output: 40000
|
max_tool_output: 40000
|
||||||
|
character: lily # Directory name in agent/characters/<character>/
|
||||||
persona:
|
|
||||||
skill: programmer # Default skill: programmer, roleplayer, analyst
|
|
||||||
|
|
||||||
character:
|
|
||||||
preset: hendrik # Directory name in agent/characters/<preset>/
|
|
||||||
skills: programmer # comma-separated, e.g. "programmer,analyst"
|
|
||||||
|
|
||||||
xmpp:
|
xmpp:
|
||||||
enabled: false
|
enabled: true
|
||||||
muc_rooms: "" # comma-separated, e.g. "room1@conference.server,room2@conference.server"
|
muc_rooms: "" # comma-separated, e.g. "room1@conference.server,room2@conference.server"
|
||||||
nickname: "" # custom MUC nickname (empty = use username)
|
nickname: "" # custom MUC nickname (empty = use username)
|
||||||
selective_response: true # true = only response if mentioned/relevant
|
selective_response: true # true = only response if mentioned/relevant
|
||||||
|
|||||||
@ -129,6 +129,7 @@ def _build_personality_block(cfg: PersonalityConfig) -> str:
|
|||||||
"formal": "You speak formally and professionally, using polite language.",
|
"formal": "You speak formally and professionally, using polite language.",
|
||||||
"playful": "You are playful and cheerful, making conversations fun and lighthearted.",
|
"playful": "You are playful and cheerful, making conversations fun and lighthearted.",
|
||||||
"warm": "You are warm and friendly, making people feel comfortable and welcomed.",
|
"warm": "You are warm and friendly, making people feel comfortable and welcomed.",
|
||||||
|
"sweet": "You speak in a sweet, gentle, and caring manner — soft and endearing.",
|
||||||
}
|
}
|
||||||
parts.append(tone_map.get(cfg.tone, tone_map["casual"]))
|
parts.append(tone_map.get(cfg.tone, tone_map["casual"]))
|
||||||
|
|
||||||
@ -254,13 +255,13 @@ def build_system_prompt(
|
|||||||
Returns:
|
Returns:
|
||||||
String system prompt lengkap.
|
String system prompt lengkap.
|
||||||
"""
|
"""
|
||||||
selected_skill = (skill or SKILL).strip().lower()
|
selected_skill = (skill or "").strip().lower()
|
||||||
cfg = personality or PERSONALITY
|
cfg = personality or PERSONALITY
|
||||||
|
|
||||||
# Resolve character name
|
# Resolve character name
|
||||||
character_name = (character or os.getenv("AGENT_CHARACTER", default="")).strip().lower()
|
character_name = (character or os.getenv("AGENT_CHARACTER", default="")).strip().lower()
|
||||||
|
|
||||||
# ── Load persona.yaml dari character directory (override personality) ─────────
|
# ── Load persona.yaml dari character directory ─────────────────────────────────
|
||||||
if character_name:
|
if character_name:
|
||||||
char_dir = ENV_CHARACTERS_DIR / character_name
|
char_dir = ENV_CHARACTERS_DIR / character_name
|
||||||
persona_yaml_path = char_dir / "persona.yaml"
|
persona_yaml_path = char_dir / "persona.yaml"
|
||||||
@ -269,7 +270,6 @@ def build_system_prompt(
|
|||||||
with open(persona_yaml_path, "r", encoding="utf-8") as f:
|
with open(persona_yaml_path, "r", encoding="utf-8") as f:
|
||||||
_persona_data = yaml.safe_load(f) or {}
|
_persona_data = yaml.safe_load(f) or {}
|
||||||
if isinstance(_persona_data, dict):
|
if isinstance(_persona_data, dict):
|
||||||
# Override personality dari persona.yaml
|
|
||||||
if _persona_data.get("name"):
|
if _persona_data.get("name"):
|
||||||
cfg.name = _persona_data["name"]
|
cfg.name = _persona_data["name"]
|
||||||
if _persona_data.get("age"):
|
if _persona_data.get("age"):
|
||||||
@ -286,10 +286,12 @@ def build_system_prompt(
|
|||||||
cfg.language = _persona_data["language"]
|
cfg.language = _persona_data["language"]
|
||||||
if _persona_data.get("mood"):
|
if _persona_data.get("mood"):
|
||||||
cfg.mood = _persona_data["mood"]
|
cfg.mood = _persona_data["mood"]
|
||||||
# key "skill" (baru) atau "mode" (legacy) menentukan active skill
|
# Skill wajib dari persona.yaml
|
||||||
_skill_from_yaml = _persona_data.get("skill") or _persona_data.get("mode")
|
_skill_from_yaml = _persona_data.get("skill") or _persona_data.get("mode")
|
||||||
if _skill_from_yaml:
|
if _skill_from_yaml:
|
||||||
selected_skill = _skill_from_yaml.strip().lower()
|
selected_skill = _skill_from_yaml.strip().lower()
|
||||||
|
else:
|
||||||
|
selected_skill = ""
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[persona] Warning: gagal load persona.yaml untuk '{character_name}': {e}")
|
print(f"[persona] Warning: gagal load persona.yaml untuk '{character_name}': {e}")
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user