Nanbeige 4.1-3B实战教程:添加NPC角色切换功能与多模型路由逻辑

1. 项目背景与目标

Nanbeige 4.1-3B像素冒险聊天终端是一款融合了复古游戏美学与AI对话技术的创新应用。本教程将指导开发者如何扩展其功能,实现以下两个核心目标:

  1. NPC角色切换功能:允许用户在对话过程中自由切换不同风格的NPC角色
  2. 多模型路由逻辑:支持后端连接多个AI模型,根据角色选择自动路由到最适合的模型

完成本教程后,你将获得一个功能更丰富、交互性更强的像素风AI对话系统。

2. 环境准备与项目结构

2.1 基础环境要求

确保你的开发环境满足以下条件:

  • Python 3.8+
  • Streamlit 1.25+
  • Transformers 4.30+
  • 至少16GB内存(推荐24GB+以流畅运行3B模型)

2.2 项目目录结构

建议按以下方式组织代码:

nanbeige-chat/
├── assets/            # 存放图片、CSS等资源
├── models/            # 模型配置文件
├── utils/             # 工具函数
│   ├── npc_manager.py # NPC角色管理
│   └── router.py      # 模型路由逻辑
├── app.py             # 主应用入口
└── requirements.txt   # 依赖列表

3. 实现NPC角色切换功能

3.1 设计NPC角色配置文件

models/npc_config.json中定义角色属性:

{
  "characters": [
    {
      "id": "sage",
      "name": "NANBEIGE LV.99",
      "color": "#6BCB77",
      "description": "智慧的大贤者,擅长解答哲理问题",
      "model_type": "nanbeige-3b"
    },
    {
      "id": "warrior",
      "name": "钢铁骑士 LV.80",
      "color": "#FF6B6B",
      "description": "勇猛的战士,精通战斗策略",
      "model_type": "llama-2-7b"
    }
  ]
}

3.2 创建角色管理模块

utils/npc_manager.py中实现角色管理:

import json
from pathlib import Path

class NPCManager:
    def __init__(self, config_path="models/npc_config.json"):
        self.config = self._load_config(config_path)
        self.current_npc = self.config["characters"][0]
    
    def _load_config(self, path):
        with open(Path(__file__).parent.parent / path) as f:
            return json.load(f)
    
    def get_npc_list(self):
        return [npc["name"] for npc in self.config["characters"]]
    
    def set_current_npc(self, npc_name):
        for npc in self.config["characters"]:
            if npc["name"] == npc_name:
                self.current_npc = npc
                return True
        return False

3.3 集成到Streamlit界面

修改主应用app.py,添加角色选择器:

import streamlit as st
from utils.npc_manager import NPCManager

npc_manager = NPCManager()

# 在侧边栏添加角色选择
with st.sidebar:
    selected_npc = st.selectbox(
        "选择你的冒险伙伴",
        npc_manager.get_npc_list(),
        index=0
    )
    npc_manager.set_current_npc(selected_npc)
    
    # 显示当前角色信息
    current_npc = npc_manager.current_npc
    st.markdown(f"""
    **{current_npc['name']}**  
    {current_npc['description']}
    """)

4. 实现多模型路由逻辑

4.1 设计模型路由配置

models/model_config.json中定义可用模型:

{
  "models": [
    {
      "name": "nanbeige-3b",
      "path": "Nanbeige/Nanbeige-4.1-3B",
      "type": "nanbeige",
      "max_tokens": 2048
    },
    {
      "name": "llama-2-7b",
      "path": "meta-llama/Llama-2-7b-chat-hf",
      "type": "llama",
      "max_tokens": 4096
    }
  ]
}

4.2 创建模型路由模块

utils/router.py中实现智能路由:

from transformers import AutoModelForCausalLM, AutoTokenizer
import json
from pathlib import Path

class ModelRouter:
    def __init__(self, config_path="models/model_config.json"):
        self.config = self._load_config(config_path)
        self.loaded_models = {}
    
    def _load_config(self, path):
        with open(Path(__file__).parent.parent / path) as f:
            return json.load(f)
    
    def get_model(self, model_name):
        if model_name in self.loaded_models:
            return self.loaded_models[model_name]
        
        model_config = next(
            (m for m in self.config["models"] if m["name"] == model_name),
            None
        )
        
        if not model_config:
            raise ValueError(f"Model {model_name} not found in config")
        
        tokenizer = AutoTokenizer.from_pretrained(model_config["path"])
        model = AutoModelForCausalLM.from_pretrained(
            model_config["path"],
            device_map="auto"
        )
        
        self.loaded_models[model_name] = {
            "model": model,
            "tokenizer": tokenizer,
            "config": model_config
        }
        
        return self.loaded_models[model_name]

4.3 集成路由到对话逻辑

更新app.py中的对话处理部分:

from utils.router import ModelRouter

model_router = ModelRouter()

def generate_response(prompt, npc):
    model_info = model_router.get_model(npc["model_type"])
    tokenizer = model_info["tokenizer"]
    model = model_info["model"]
    
    inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
    outputs = model.generate(
        **inputs,
        max_new_tokens=model_info["config"]["max_tokens"],
        pad_token_id=tokenizer.eos_token_id
    )
    
    return tokenizer.decode(outputs[0], skip_special_tokens=True)

# 在对话逻辑中使用
user_input = st.chat_input("输入你的冒险指令...")
if user_input:
    response = generate_response(user_input, npc_manager.current_npc)
    # 显示对话气泡...

5. 优化与进阶功能

5.1 添加角色特定提示词

为每个角色定制系统提示,在npc_config.json中添加:

{
  "id": "sage",
  "system_prompt": "你是一位智慧的大贤者,回答问题时应该充满哲理..."
}

然后在生成响应前拼接提示词:

def generate_response(prompt, npc):
    full_prompt = f"{npc['system_prompt']}\n\n用户: {prompt}\n{npc['name']}:"
    # 剩余生成逻辑...

5.2 实现对话历史持久化

使用Streamlit的session state保存对话历史:

if "history" not in st.session_state:
    st.session_state.history = []

# 在生成响应后
st.session_state.history.append({
    "npc": npc_manager.current_npc["name"],
    "user": user_input,
    "bot": response
})

5.3 添加角色切换动画效果

使用CSS实现平滑过渡:

st.markdown("""
<style>
@keyframes npcChange {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
}
.npc-change {
    animation: npcChange 0.3s ease-out;
}
</style>
""", unsafe_allow_html=True)

6. 总结与下一步

通过本教程,我们实现了:

  1. NPC角色切换系统:用户可以自由选择不同风格的角色进行对话
  2. 智能模型路由:根据角色配置自动选择最适合的AI模型
  3. 扩展性架构:便于添加新角色和模型

下一步可以考虑:

  • 添加更多角色和模型选择
  • 实现角色特定的对话风格和语气
  • 优化模型加载策略,减少内存占用

获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐