custom model per character
This commit is contained in:
parent
b052fccf0f
commit
85e4a0d17e
87
config.py
87
config.py
@ -237,6 +237,93 @@ def load_service_config(char_override=None):
|
||||
TELEGRAM_SELECTIVE_RESPONSE = str(telegram_data["selective_response"]).strip().lower() in ("true", "1", "yes")
|
||||
|
||||
|
||||
# ─── Model Config (model.yaml per karakter) ────────────────────────────────────
|
||||
|
||||
MODEL_YAML_PATH = None # Path model.yaml milik karakter aktif, jika ada
|
||||
CHARACTER_MODELS = {} # {type_name: model_set_name} dari model.yaml
|
||||
|
||||
|
||||
def _reset_model_config():
|
||||
"""Reset konfigurasi model dari model.yaml."""
|
||||
global MODEL_YAML_PATH, CHARACTER_MODELS
|
||||
MODEL_YAML_PATH = None
|
||||
CHARACTER_MODELS = {}
|
||||
|
||||
|
||||
def load_model_config(char_override=None):
|
||||
"""Terapkan model.yaml milik karakter aktif ke default moop (sqlite).
|
||||
|
||||
Jika file agent/characters/<char>/model.yaml ada, tiap tipe yang terisi
|
||||
(llm/embedding/imagegen/imagevision) akan dijadikan default model set
|
||||
untuk tipe tersebut. Tipe kosong/missing tidak diubah; karakter tanpa
|
||||
model.yaml akan memakai default yang sudah ada.
|
||||
|
||||
Mengubah default DB (moop.set_default) sehingga berlaku persist, sama
|
||||
seperti aksi 'set as default' di TUI. import moop dilakukan lazy untuk
|
||||
menghindari circular import (moop meng-import config).
|
||||
"""
|
||||
global MODEL_YAML_PATH, CHARACTER_MODELS
|
||||
|
||||
_reset_model_config()
|
||||
|
||||
if char_override:
|
||||
cfg_char = char_override.strip().lower()
|
||||
else:
|
||||
cfg_char = AGENT_CHARACTER
|
||||
|
||||
if not cfg_char:
|
||||
return
|
||||
|
||||
model_yaml_path = CHARACTERS_DIR / cfg_char / "model.yaml"
|
||||
if not model_yaml_path.is_file():
|
||||
return
|
||||
|
||||
try:
|
||||
data = yaml.safe_load(model_yaml_path.read_text(encoding="utf-8")) or {}
|
||||
if not isinstance(data, dict):
|
||||
data = {}
|
||||
except Exception as _e:
|
||||
print(f"[config] Warning: gagal load model.yaml untuk '{cfg_char}': {_e}", flush=True)
|
||||
return
|
||||
|
||||
if not data:
|
||||
return
|
||||
|
||||
from lib import moop # lazy import
|
||||
|
||||
applied = []
|
||||
for tname in moop.MODEL_TYPES:
|
||||
value = data.get(tname)
|
||||
if value is None:
|
||||
continue
|
||||
set_name = str(value).strip()
|
||||
if not set_name:
|
||||
continue
|
||||
s = moop.get_set_by_name(None, set_name)
|
||||
if not s:
|
||||
print(
|
||||
f"[config] Warning: model.yaml '{cfg_char}' merujuk set "
|
||||
f"'{set_name}' untuk tipe '{tname}', tapi set tidak ditemukan. Diabaikan.",
|
||||
flush=True,
|
||||
)
|
||||
continue
|
||||
chain = moop.resolve_chain(None, s["id"])
|
||||
if not chain:
|
||||
print(
|
||||
f"[config] Warning: model.yaml '{cfg_char}' merujuk set "
|
||||
f"'{set_name}' untuk tipe '{tname}', tapi set tidak punya model aktif. Diabaikan.",
|
||||
flush=True,
|
||||
)
|
||||
continue
|
||||
moop.set_default(None, tname, s["id"])
|
||||
CHARACTER_MODELS[tname] = set_name
|
||||
applied.append(f"{tname}={set_name}")
|
||||
|
||||
if applied:
|
||||
MODEL_YAML_PATH = model_yaml_path
|
||||
print(f"[config] Model config dari model.yaml: {', '.join(applied)}", flush=True)
|
||||
|
||||
|
||||
# Load character & service dari config.yaml saat import time
|
||||
load_character()
|
||||
load_service_config()
|
||||
|
||||
@ -78,6 +78,8 @@ def main():
|
||||
# Override char configuration from args
|
||||
if args.char:
|
||||
config.load_service_config(char_override=args.char)
|
||||
# Terapkan model.yaml milik karakter aktif (jika ada) ke default moop
|
||||
config.load_model_config()
|
||||
# Set workspace from args
|
||||
if args.workspace:
|
||||
resolved = os.path.abspath(args.workspace)
|
||||
|
||||
12
lib/moop.py
12
lib/moop.py
@ -235,6 +235,18 @@ def get_set(path=None, set_id=None):
|
||||
conn.close()
|
||||
|
||||
|
||||
def get_set_by_name(path=None, name=""):
|
||||
"""Cari model set berdasarkan nama (case-insensitive). Returns None jika tidak ada."""
|
||||
name = (name or "").strip()
|
||||
if not name:
|
||||
return None
|
||||
target = name.lower()
|
||||
for s in list_sets(path):
|
||||
if (s.get("name") or "").strip().lower() == target:
|
||||
return s
|
||||
return None
|
||||
|
||||
|
||||
def create_set(path=None, name=""):
|
||||
conn = _connect(path)
|
||||
try:
|
||||
|
||||
@ -2,14 +2,17 @@ import gc, sys, uuid, lancedb
|
||||
import config, lib.ragroleplay as ragroleplay_lib
|
||||
from lib import personality
|
||||
|
||||
_emb_url, _emb_model = ragroleplay_lib.embedding_endpoint()
|
||||
|
||||
_EMB_GUIDANCE = "Ragroleplay butuh embedding model set. Atur dulu di TUI: Model > Manage Sets (Model Option), tipe 'embedding'."
|
||||
|
||||
def _get_emb():
|
||||
ep = ragroleplay_lib.embedding_endpoint()
|
||||
if ep:
|
||||
return ep[0], ep[1]
|
||||
return None, None
|
||||
|
||||
def _emb_ready():
|
||||
if not _emb_url or not _emb_model:
|
||||
return False
|
||||
return True
|
||||
_url, _model = _get_emb()
|
||||
return bool(_url and _model)
|
||||
|
||||
def _uuid(val):
|
||||
if isinstance(val, str):
|
||||
@ -45,8 +48,7 @@ def users_store(fullname, nickname, character, id=None, alias=None, salutation=N
|
||||
try:
|
||||
success = ragroleplay_lib.users_store(
|
||||
config.ragroleplay_db_path,
|
||||
_emb_url,
|
||||
_emb_model,
|
||||
*_get_emb(),
|
||||
fullname,
|
||||
nickname,
|
||||
alias,
|
||||
@ -542,7 +544,7 @@ def memories_check(prompt_text, search_limit):
|
||||
try:
|
||||
db = lancedb.connect(config.ragroleplay_db_path)
|
||||
table = db.open_table("knowledge_memories")
|
||||
query_vector = ragroleplay_lib.embed_text(_emb_url, _emb_model, prompt_text)
|
||||
query_vector = ragroleplay_lib.embed_text(*_get_emb(), prompt_text)
|
||||
results = table.search(query_vector, vector_column_name="vector_context").limit(search_limit).to_list()
|
||||
|
||||
if not results:
|
||||
@ -578,8 +580,7 @@ def memories_store(character, user, event, category, detail, physical, emotional
|
||||
try:
|
||||
success = ragroleplay_lib.memories_store(
|
||||
config.ragroleplay_db_path,
|
||||
_emb_url,
|
||||
_emb_model,
|
||||
*_get_emb(),
|
||||
character,
|
||||
_uuid(user),
|
||||
event,
|
||||
@ -622,8 +623,7 @@ def memories_summarize(prompt_text, search_limit=5):
|
||||
result = ragroleplay_lib.memories_summarize(
|
||||
config.ragroleplay_db_path,
|
||||
prompt_text,
|
||||
_emb_url,
|
||||
_emb_model,
|
||||
*_get_emb(),
|
||||
search_limit
|
||||
)
|
||||
return result
|
||||
@ -658,8 +658,7 @@ def memories_update(memory_id, **updates):
|
||||
try:
|
||||
success = ragroleplay_lib.memories_update(
|
||||
config.ragroleplay_db_path,
|
||||
_emb_url,
|
||||
_emb_model,
|
||||
*_get_emb(),
|
||||
_uuid(memory_id),
|
||||
**updates
|
||||
)
|
||||
@ -715,8 +714,7 @@ def users_update(user_id, **updates):
|
||||
try:
|
||||
success = ragroleplay_lib.users_update(
|
||||
config.ragroleplay_db_path,
|
||||
_emb_url,
|
||||
_emb_model,
|
||||
*_get_emb(),
|
||||
_uuid(user_id),
|
||||
**updates
|
||||
)
|
||||
@ -741,7 +739,7 @@ def users_delete(user_id):
|
||||
def objects_store(keyword, when, where, name, description, shape, usage):
|
||||
if not _emb_ready(): return _EMB_GUIDANCE
|
||||
try:
|
||||
success = ragroleplay_lib.objects_store(config.ragroleplay_db_path, _emb_url, _emb_model, keyword, when, where, name, description, shape, usage)
|
||||
success = ragroleplay_lib.objects_store(config.ragroleplay_db_path, *_get_emb(), keyword, when, where, name, description, shape, usage)
|
||||
return "Berhasil menyimpan objek baru." if success else "Gagal menyimpan objek."
|
||||
except Exception as e: return f"Error: {str(e)}"
|
||||
|
||||
@ -758,7 +756,7 @@ def objects_filter(keyword=None, object_id=None):
|
||||
def objects_update(object_id, **updates):
|
||||
if not _emb_ready(): return _EMB_GUIDANCE
|
||||
try:
|
||||
success = ragroleplay_lib.objects_update(config.ragroleplay_db_path, _emb_url, _emb_model, _uuid(object_id), **updates)
|
||||
success = ragroleplay_lib.objects_update(config.ragroleplay_db_path, *_get_emb(), _uuid(object_id), **updates)
|
||||
return "Berhasil memperbarui objek." if success else "Gagal memperbarui objek."
|
||||
except Exception as e: return f"Error: {str(e)}"
|
||||
|
||||
@ -772,7 +770,7 @@ def objects_delete(object_id):
|
||||
def outfits_store(keyword, when, outfit):
|
||||
if not _emb_ready(): return _EMB_GUIDANCE
|
||||
try:
|
||||
success = ragroleplay_lib.outfits_store(config.ragroleplay_db_path, _emb_url, _emb_model, keyword, when, outfit)
|
||||
success = ragroleplay_lib.outfits_store(config.ragroleplay_db_path, *_get_emb(), keyword, when, outfit)
|
||||
return "Berhasil menyimpan outfit baru." if success else "Gagal menyimpan outfit."
|
||||
except Exception as e: return f"Error: {str(e)}"
|
||||
|
||||
@ -789,7 +787,7 @@ def outfits_filter(keyword=None, outfit_id=None):
|
||||
def outfits_update(outfit_id, **updates):
|
||||
if not _emb_ready(): return _EMB_GUIDANCE
|
||||
try:
|
||||
success = ragroleplay_lib.outfits_update(config.ragroleplay_db_path, _emb_url, _emb_model, _uuid(outfit_id), **updates)
|
||||
success = ragroleplay_lib.outfits_update(config.ragroleplay_db_path, *_get_emb(), _uuid(outfit_id), **updates)
|
||||
return "Berhasil memperbarui outfit." if success else "Gagal memperbarui outfit."
|
||||
except Exception as e: return f"Error: {str(e)}"
|
||||
|
||||
@ -803,7 +801,7 @@ def outfits_delete(outfit_id):
|
||||
def todos_store(keyword, when, do):
|
||||
if not _emb_ready(): return _EMB_GUIDANCE
|
||||
try:
|
||||
success = ragroleplay_lib.todos_store(config.ragroleplay_db_path, _emb_url, _emb_model, keyword, when, do)
|
||||
success = ragroleplay_lib.todos_store(config.ragroleplay_db_path, *_get_emb(), keyword, when, do)
|
||||
return "Berhasil menyimpan to-do baru." if success else "Gagal menyimpan to-do."
|
||||
except Exception as e: return f"Error: {str(e)}"
|
||||
|
||||
@ -820,7 +818,7 @@ def todos_filter(keyword=None, todo_id=None):
|
||||
def todos_update(todo_id, **updates):
|
||||
if not _emb_ready(): return _EMB_GUIDANCE
|
||||
try:
|
||||
success = ragroleplay_lib.todos_update(config.ragroleplay_db_path, _emb_url, _emb_model, _uuid(todo_id), **updates)
|
||||
success = ragroleplay_lib.todos_update(config.ragroleplay_db_path, *_get_emb(), _uuid(todo_id), **updates)
|
||||
return "Berhasil memperbarui to-do." if success else "Gagal memperbarui to-do."
|
||||
except Exception as e: return f"Error: {str(e)}"
|
||||
|
||||
@ -834,7 +832,7 @@ def todos_delete(todo_id):
|
||||
def worlds_store(category, location, description):
|
||||
if not _emb_ready(): return _EMB_GUIDANCE
|
||||
try:
|
||||
success = ragroleplay_lib.worlds_store(config.ragroleplay_db_path, _emb_url, _emb_model, category, location, description)
|
||||
success = ragroleplay_lib.worlds_store(config.ragroleplay_db_path, *_get_emb(), category, location, description)
|
||||
return "Berhasil menyimpan lokasi dunia baru." if success else "Gagal menyimpan lokasi dunia."
|
||||
except Exception as e: return f"Error: {str(e)}"
|
||||
|
||||
@ -851,7 +849,7 @@ def worlds_filter(category=None, location=None, world_id=None):
|
||||
def worlds_update(world_id, **updates):
|
||||
if not _emb_ready(): return _EMB_GUIDANCE
|
||||
try:
|
||||
success = ragroleplay_lib.worlds_update(config.ragroleplay_db_path, _emb_url, _emb_model, _uuid(world_id), **updates)
|
||||
success = ragroleplay_lib.worlds_update(config.ragroleplay_db_path, *_get_emb(), _uuid(world_id), **updates)
|
||||
return "Berhasil memperbarui lokasi dunia." if success else "Gagal memperbarui lokasi dunia."
|
||||
except Exception as e: return f"Error: {str(e)}"
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user