我用AI生成的《谁杀死了比尔?》游戏中的AI对话实现详解

点击《谁杀死了比尔?》开始你的推理之旅吧!!!

API

游戏中AI与玩家对话的核心就是通过调用大模型的API接口实现的,具体流程如下:

1. API的配置

javascript 复制代码
const AI_CONFIG = {
    apiKey: 'api_key',
    endpoint: 'URL',
    model: 'name' // 指定的大模型名称
};
  • endpoint(端点)

endpoint指的就是你要发送HTTP请求的服务器地址(URL),也就是API服务的入口网址。你发送的所有请求(如POST、GET等)都要发送到这个地址,服务器才会处理你的请求并返回结果。

2. API的调用

javascript 复制代码
    // 调用豆包AI API
    async callDoubaoAPI(question) {
            const response = await fetch(AI_CONFIG.endpoint, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${AI_CONFIG.apiKey}`,
                    'X-Request-Id': Date.now().toString()
                },
                body: JSON.stringify({  
                    model: AI_CONFIG.model,
                    messages: [{
                        role: 'user',
                        content: this.buildPrompt(question)
                    }],
                    max_tokens: 300,
                    temperature: 0.7,
                    stream: false
                })
            });
        }
    }

这里呢,使用的是async/await关键字能让异步操作看起来像同步操作(实际上仍然是异步执行),这样让API调用的整个代码可读性变好。可阅读往期文章《从Promise到async/await的逻辑演进》了解async/await的作用和效果。

  • method

在我的游戏中,调用AI接口时用的是POST提交一段数据(用户的问题和Prompt)。

method 是 HTTP 请求中的一个重要参数,用来指定你要对服务器做什么操作。它就像你去银行窗口时告诉柜员"我要存钱"还是"我要取钱"一样,服务器会根据你说的"操作类型"来决定怎么处理你的请求。常见的HTTP method有GET (获取数据)、POST (提交数据)、PUT(更新数据)和DELETE(删除数据)。其中常用的是GET和POST,但为什么不用GET?因为GET 请求一般只用来"获取"信息,不能带复杂的body数据(比如你的Prompt),而POST请求可以带上大量、结构化的数据(如JSON),适合AI对话、表单提交等场景。

  • headers(请求头)
    • Content-Type: application/json
    • Authorization: Bearer <apiKey>
    • X-Request-Id: <唯一请求ID>

请求头 (HTTP Headers)是HTTP协议中每个请求都会携带的一组键值对信息,用来告诉服务器关于本次请求的各种"元信息"。就好像是寄快递时快递贴的标签,说明快递里面是什么、谁寄的、怎么处理等。各种"元信息"如下:

Content: 说明数据的格式,告诉服务器发过来的是JSON格式,按JSON解析。

Authorization: 告诉服务器具有权限(携带密钥),允许访问服务。

X-Request-Id: 通常用的是时间戳,用来给每个请求一个唯一编号,方便服务器日志追踪和排查问题

  • body(请求体)
    • model:AI模型名称(如doubao-1-5-pro-32k-250115
    • messages:对话内容数组,通常只传一条,内容为构建好的Prompt
    • max_tokens:最大返回token数(如300)
    • temperature:采样温度,控制回答随机性(如0.7)
    • stream:是否流式返回(本游戏用false)

细节: 使用JSON.stringify作用是为了将JavaScript对象转为JSON字符串,因为HTTP请求只能传输文本,不能直接传输JavaScript对象。

例子比如:

javascript 复制代码
  // 转换前(JavaScript对象)
  { name: "Tom" }
  // 转换后(JSON字符串)
  '{"name":"Tom"}'
  • messages数组
javascript 复制代码
messages: [{
    role: 'user',
    content: this.buildPrompt(question)
}]

messages数组 包含了role (角色)即消息的发送者角色包括'user'(用户发送的消息)、'assistant'(AI的回复)和'system'(系统指令)和content 即具体的消息内容(这是是通过buildPrompt方法构建的提示词)

  • max_tokens

限制AI回答的最大长度,单位是token(大约1个汉字=2个token,1个英文单词=1-2个token),之所以限制是为了控制响应的时间,API调用成本,还有确保回答简洁凝练。

  • temperature

temperature 是为了控制AI回答的随机性/创造性,取值范围在0.0-1.0,其中0.0表示非常确定,总是选择最可能的词;0.7表示中等随机性,比较准确又自然的对话(常用这个值 );1.0表示最随机,更有创造性但是不够准确。

  • stream

是否使用流式返回,要么true要么false,即是否逐字返回输出。

提示词构建

提示词构建,即构建发送AI的提示词

javascript 复制代码
buildPrompt(question) {

    return {
        prompt: `### 角色设定
    你是一个侦探游戏《谁杀死了比尔?》中的AI助手。

    ### 案件背景
    时间:
    地点:
    死者:
    死因:
    现场发现:

    ### 人物信息

    ### 回答规则
    1. 保持简洁:回答控制在100字以内
    2. 实事求是:只说已知的事实,不要推测
    3. 不剧透:绝对不能直接或暗示谁是凶手
    4. 态度友好:用轻松自然的语气交谈
    5. 适时提醒:遇到关键线索要提醒玩家记录

    ### 对话历史
    ${this.formatConversationHistory()}

    ### 当前问题
    ${question}

    请根据以上设定回答问题。`,
        context: this.context
    };
}

提示词构建(Prompt Engineering)的作用是:通过精心设计的文本指令,让AI准确理解游戏背景、规则和要求,从而以合适的身份、语气和方式回答玩家问题,既能推动剧情又不会剧透,确保游戏的趣味性和神秘感。

总结

立即开始你的交互式AI对话之旅吧!

相关推荐
晓131313 分钟前
JavaScript基础篇——第五章 对象(最终篇)
开发语言·前端·javascript
EdisonZhou21 分钟前
多Agent协作入门:群组聊天-AgentGroupChat
llm·aigc·.net core
灋✘逞_兇41 分钟前
Node.Js是什么?
服务器·javascript·node.js
后端小肥肠1 小时前
揭秘10W+AI动物运动会视频,我用Coze一键搞定全流程(附保姆级拆解)
人工智能·aigc·coze
小飞悟2 小时前
那些年我们忽略的高频事件,正在拖垮你的页面
javascript·设计模式·面试
中微子2 小时前
闭包面试宝典:高频考点与实战解析
前端·javascript
G等你下课2 小时前
告别刷新就丢数据!localStorage 全面指南
前端·javascript
爱编程的喵2 小时前
JavaScript闭包实战:从类封装到防抖函数的深度解析
前端·javascript
m0_743106462 小时前
【论文笔记】BlockGaussian:巧妙解决大规模场景重建中的伪影问题
论文阅读·计算机视觉·3d·aigc·几何学
前端Hardy3 小时前
8个你必须掌握的「Vue」实用技巧
前端·javascript·vue.js