feat(ai): add per-character AI model assignment and identity profiles
Implements deterministic model resolution (column → env map → pool → default) and adds AI identity fields to characters. Migration backfills existing rows with deterministic defaults. Controller uses resolved model and identity block in system prompts for contextual conversations.
This commit is contained in:
@@ -1,5 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Character model map parser
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Turns AI_CHARACTER_MODELS entries such as "Maria=qwen/qwen3.7-flash:free"
|
||||
| or "3=deepseek/deepseek-v4-flash-0731" into a lookup array keyed by
|
||||
| lowercased character id or name. Invalid pairs are ignored.
|
||||
|
|
||||
*/
|
||||
$parseCharacterModels = static function (string $raw): array {
|
||||
$map = [];
|
||||
|
||||
foreach (explode(',', $raw) as $pair) {
|
||||
$pair = trim($pair);
|
||||
if ($pair === '' || ! str_contains($pair, '=')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[$key, $model] = array_map('trim', explode('=', $pair, 2));
|
||||
if ($key !== '' && $model !== '') {
|
||||
$map[strtolower($key)] = $model;
|
||||
}
|
||||
}
|
||||
|
||||
return $map;
|
||||
};
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
@@ -50,8 +78,43 @@ return [
|
||||
'poolside/laguna-xs-2.1:free',
|
||||
'inclusionai/ling-3.0-flash-vl:free',
|
||||
'qwen/qwen3.7-flash:free',
|
||||
// Verified working free chat models (live probe of the OpenRouter
|
||||
// catalogue). Safe defaults for per-character assignment.
|
||||
'deepseek/deepseek-v4-flash-0731',
|
||||
'nvidia/nemotron-3.5-lightning:free',
|
||||
'liquid/lfm-2.5-2.6b:free',
|
||||
'openrouter/free',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Per-Character Model Pool (AI_MODELS)
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Comma-separated allow-listed models distributed deterministically
|
||||
| across characters (each character keeps a stable own model). Falls
|
||||
| back to AI_DEFAULT_MODEL when empty.
|
||||
|
|
||||
*/
|
||||
|
||||
'models' => array_values(array_filter(array_map(
|
||||
'trim',
|
||||
explode(',', (string) env('AI_MODELS', ''))
|
||||
))),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Per-Character Model Map (AI_CHARACTER_MODELS)
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Explicit "id or name = model" overrides from the environment, e.g.
|
||||
| "Maria=liquid/lfm-2.5-2.6b:free,7=openrouter/free". Takes priority
|
||||
| over the pool; entries outside the allow-list are ignored.
|
||||
|
|
||||
*/
|
||||
|
||||
'character_models' => $parseCharacterModels((string) env('AI_CHARACTER_MODELS', '')),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Model
|
||||
|
||||
Reference in New Issue
Block a user