From 0350cad2533b53b493b040c0ed51fc592fa10aba Mon Sep 17 00:00:00 2001 From: bridge Date: Tue, 28 Oct 2025 00:33:48 +0800 Subject: [PATCH] remove rule ai --- src/classes/ai.py | 75 +++++--------------------------------------- src/sim/simulator.py | 7 ++--- static/config.yml | 9 +++--- 3 files changed, 13 insertions(+), 78 deletions(-) diff --git a/src/classes/ai.py b/src/classes/ai.py index 6bcaa7e..f275f47 100644 --- a/src/classes/ai.py +++ b/src/classes/ai.py @@ -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() \ No newline at end of file +llm_ai = LLMAI() \ No newline at end of file diff --git a/src/sim/simulator.py b/src/sim/simulator.py index 1111970..b076635 100644 --- a/src/sim/simulator.py +++ b/src/sim/simulator.py @@ -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 diff --git a/static/config.yml b/static/config.yml index 11ed8d9..c62f8ec 100644 --- a/static/config.yml +++ b/static/config.yml @@ -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: