remove rule ai

This commit is contained in:
bridge
2025-10-28 00:33:48 +08:00
parent d2f8205355
commit 0350cad253
3 changed files with 13 additions and 78 deletions

View File

@@ -1,19 +1,15 @@
"""
NPC AI的类。
这里指的不是LLM或者Machine Learning是NPC的决策机制
分为两类规则AI和LLM AI
NPC AI 的类。
这里指的是 NPC 的决策机制
"""
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING
import random
from src.classes.world import World
from src.classes.region import Region
from src.classes.root import get_essence_types_for_root
from src.classes.event import Event, NULL_EVENT
from src.utils.llm import get_ai_prompt_and_call_llm_async
from src.classes.typings import ACTION_NAME, ACTION_PARAMS, ACTION_PAIR, ACTION_NAME_PARAMS_PAIRS
from src.classes.typings import ACTION_NAME_PARAMS_PAIRS
from src.utils.config import CONFIG
from src.classes.actions import ACTION_INFOS_STR
@@ -34,8 +30,8 @@ class AI(ABC):
async def decide(self, world: World, avatars_to_decide: list[Avatar]) -> dict[Avatar, tuple[ACTION_NAME_PARAMS_PAIRS, str, str, Event]]:
"""
决定做什么,同时生成对应的事件。
一个ai支持批量生成多个avatar的动作。
这对LLM AI节省时间和token非常有意义。
一个 AI 支持批量生成多个 avatar 的动作。
这对 LLM AI 节省时间和 token 非常有意义。
"""
results = {}
max_decide_num = CONFIG.ai.max_decide_num
@@ -43,68 +39,12 @@ class AI(ABC):
results.update(await self._decide(world, avatars_to_decide[i:i+max_decide_num]))
for avatar, result in list(results.items()):
# 兼容RuleAI 返回单动作LLMAI 返回动作链
if result and isinstance(result[0], list):
action_name_params_pairs, avatar_thinking, objective = result # type: ignore
else:
action_name, action_params, avatar_thinking, objective = result # type: ignore
action_name_params_pairs = [(action_name, action_params)]
action_name_params_pairs, avatar_thinking, objective = result # type: ignore
# 不在决策阶段生成开始事件,提交阶段统一触发
results[avatar] = (action_name_params_pairs, avatar_thinking, objective, NULL_EVENT)
return results
class RuleAI(AI):
"""
规则AI批量接口内部逐个决策
"""
def __decide(self, world: World, avatar: "Avatar", regions: list[Region]) -> tuple[ACTION_NAME, ACTION_PARAMS, str, str]:
"""
单个 Avatar 的决策逻辑。
先做一个简单的:
1. 找到自己灵根对应的最好的区域
2. 检测自己是否在最好的区域
3. 如果不在,则移动到最好的区域
4. 如果已经到达最好的区域,则进行修炼
5. 如果需要突破境界了,则突破境界
"""
if random.random() < 0.1:
return ("Play", {}, "", "放松一下,缓解修行压力")
best_region = self.get_best_region_for_avatar(avatar, regions)
if avatar.is_in_region(best_region):
if avatar.cultivation_progress.can_break_through():
return ("Breakthrough", {}, "", "尽快突破到更高境界")
else:
return ("Cultivate", {}, "", "稳步提升修为")
else:
return ("MoveToRegion", {"region": best_region.name}, "", f"前往{best_region.name}修行")
async def _decide(self, world: World, avatars_to_decide: list[Avatar]) -> dict[Avatar, tuple[ACTION_NAME, ACTION_PARAMS, str, str]]:
"""
决策逻辑:批量接口的实现上,逐个 Avatar 调用 __decide 进行独立决策,
以保持规则AI的可控性与可测试性。
"""
results: dict[Avatar, tuple[ACTION_NAME, ACTION_PARAMS, str, str]] = {}
regions: list[Region] = list(world.map.regions.values())
for avatar in avatars_to_decide:
results[avatar] = self.__decide(world, avatar, regions)
return results
def get_best_region_for_avatar(self, avatar: "Avatar", regions: list[Region]) -> Region:
"""
根据avatar的灵根找到最适合的区域
"""
essence_types = get_essence_types_for_root(avatar.root)
def best_density(region: Region) -> int:
return max((region.essence.get_density(et) for et in essence_types), default=0)
region_with_best_essence = max(regions, key=best_density)
return region_with_best_essence
class LLMAI(AI):
"""
LLM AI
@@ -154,5 +94,4 @@ class LLMAI(AI):
results[avatar] = (pairs, avatar_thinking, objective)
return results
llm_ai = LLMAI()
rule_ai = RuleAI()
llm_ai = LLMAI()

View File

@@ -7,7 +7,7 @@ from src.classes.age import Age
from src.classes.cultivation import Realm
from src.classes.world import World
from src.classes.event import Event, is_null_event
from src.classes.ai import llm_ai, rule_ai
from src.classes.ai import llm_ai
from src.utils.names import get_random_name
from src.utils.config import CONFIG
from src.run.log import get_logger
@@ -29,10 +29,7 @@ class Simulator:
avatars_to_decide.append(avatar)
if not avatars_to_decide:
return
if CONFIG.ai.mode == "llm":
ai = llm_ai
else:
ai = rule_ai
ai = llm_ai
decide_results = await ai.decide(self.world, avatars_to_decide)
for avatar, result in decide_results.items():
action_name_params_pairs, avatar_thinking, objective, _event = result

View File

@@ -1,9 +1,9 @@
llm:
# 填入litellm支持的model name和key
model_name: "your-model-name"
fast_model_name: "your-fast-model-name"
key: "your-api-key"
base_url: "your-base-url-of-llm"
key: "your-api-key" # 目前需要的是阿里的qwen api
model_name: "openai/qwen-plus"
fast_model_name: "openai/qwen-flash"
base_url: "https://dashscope.aliyuncs.com/compatible-mode/v1"
max_parse_retries: 3
paths:
@@ -11,7 +11,6 @@ paths:
game_configs: static/game_configs/
ai:
mode: "llm" # "rule" or "llm"
max_decide_num: 4
game: