Files
cultivation-world-simulator/src/classes/single_choice.py
2026-01-03 22:30:33 +08:00

104 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from typing import Any, Dict, List, TYPE_CHECKING
from src.utils.llm import call_llm_with_task_name
from src.utils.config import CONFIG
import json
if TYPE_CHECKING:
from src.classes.avatar import Avatar
async def make_decision(
avatar: "Avatar",
context_desc: str,
options: List[Dict[str, Any]]
) -> str:
"""
让角色在多个选项中做出单选决策。
Args:
avatar: 做出决策的角色
context_desc: 决策背景描述
options: 选项列表,每个选项是一个字典,必须包含 'key''desc' 字段
例如: [{'key': 'A', 'desc': '...'}, {'key': 'B', 'desc': '...'}]
Returns:
str: AI 选择的选项 Key (如 'A''B')
"""
# 1. 获取角色信息 (详细模式)
avatar_infos = str(avatar.get_info(detailed=True))
# 2. 格式化选项字符串
choices_list = [f"{opt.get('key', '')}: {opt.get('desc', '')}" for opt in options]
choices_str = "\n".join(choices_list)
full_choices_str = f"【当前情境】:{context_desc}\n\n{choices_str}"
# 3. 调用 AI
template_path = CONFIG.paths.templates / "single_choice.txt"
world_info = avatar.world.static_info
result = await call_llm_with_task_name(
"single_choice",
template_path,
infos={
"world_info": world_info,
"avatar_infos": avatar_infos,
"choices": full_choices_str
}
)
# 4. 解析结果
choice = ""
if isinstance(result, dict):
choice = result.get("choice", "").strip()
elif isinstance(result, str):
clean_result = result.strip()
# 尝试解析可能包含 markdown 的 json
if "{" in clean_result and "}" in clean_result:
try:
# 提取可能的 json 部分
start = clean_result.find("{")
end = clean_result.rfind("}") + 1
json_str = clean_result[start:end]
data = json.loads(json_str)
choice = data.get("choice", "").strip()
except (json.JSONDecodeError, ValueError):
# 如果 JSON 解析失败,直接看字符串内容是否就是选项 key
choice = clean_result
# 有时候 llm 会输出 "choice: A",这里做个兼容
else:
choice = clean_result
# 验证 choice 是否在 options key 中
valid_keys = {opt["key"] for opt in options}
# 简单的容错:如果返回的是 "A." 或者 "A "
if choice not in valid_keys:
for k in valid_keys:
if k in choice:
choice = k
break
if choice not in valid_keys:
# 兜底:默认选第一个
choice = options[0]["key"]
return choice
def format_swap_choice_desc(new_item: Any, old_item: Any | None, item_type_name: str) -> str:
"""
生成替换装备/功法时的决策描述文本。
Args:
new_item: 新获得的物品对象(必须实现 get_info(detailed=True)
old_item: 当前持有的物品对象(可能为 None
item_type_name: 物品类型名称(如"兵器""功法"
"""
new_info = new_item.get_info(detailed=True)
if old_item:
old_info = old_item.get_info(detailed=True)
return (
f"现有{item_type_name}{old_info}\n"
f"{item_type_name}{new_info}\n"
f"(选择替换将卖出旧{item_type_name}"
)
else:
return f"{item_type_name}{new_info}"