在今天的教程中,我们将介绍如何使用 SendAI 的 Solana Agent Kit 构建一个 DeFAI 加密货币 Discord 机器人。借助该机器人,用户可以轻松执行链上任务,例如查看加密货币价格和市场统计数据、跟踪钱包余额以及向其他用户发送代币。
与往常一样,我们将在文章末尾附上带有示例实现的 GitHub 存储库链接。
什么是 DeFAI?(去中心化金融人工智能)
DeFAI(去中心化金融 + 人工智能)是指由人工智能驱动的代理,能够与 DeFi 协议交互或集成,从而提升效率。这些人工智能代理可以通过文本提示执行复杂的链上操作,例如兑换和创建代币、获取市场数据以及发送代币。
这有助于简化围绕与链上协议交互的通常复杂的过程。
现在,让我们深入创建我们自己的 Discord DeFAI 代理!
要求
以下是您需要遵循本指南的内容:
-
CoinGeckoAPI密钥
-
Discord 服务器
-
Discord 机器人代币
-
Node.js 22.14.0 + npm(或 pnpm)
-
Solana 钱包私钥
-
RPC网关
-
OpenAI API 密钥
-
困惑之钥
创建Discord服务器
登录你的 Discord 帐户,然后点击服务器侧边栏左下角的加号 (+)。选择服务器名称,然后点击“创建”。
创建Discord机器人
在 Discord 上,我们必须先创建一个应用程序并定义其作用域,然后才能创建机器人。为此,请导航到开发者仪表板,然后点击右上角的“新建应用程序” 。
给你的机器人起个名字,然后在Bot下点击Reset Token。我们需要这个令牌来在我们的应用程序中与机器人进行身份验证,所以现在只需将它存储在安全的地方即可。
接下来,我们需要定义机器人的使用范围并将其邀请到我们的服务器。在“机器人”下,向下滚动到“机器人权限”。
在这里,您将定义机器人加入服务器时所需的各种权限。请确保仅选择必需的范围,因为选择所有内容可能会使您的服务器面临风险。对于对话机器人,我们只需要它能够读取消息历史记录和发送消息。
在此部分的正下方,您将看到一个名为“Permissions Integer”的值。
记下这个,因为我们需要它来以正确的权限邀请我们的机器人加入服务器。要邀请机器人加入你的服务器,请导航到“安装”部分,然后复制“安装链接”。
在将 URL 粘贴到浏览器之前,您需要附加以下参数:&permissions和&scope,其中 permissions 代表您之前复制的权限整数,scope 代表应用程序类型,在本例中为机器人。
您的最终 URL 应类似于以下内容:
https://discord.com/oauth2/authorize?client_id=1111111111111111111&permisisons=67584&scope=bot
将其粘贴到您的浏览器中,您将被重定向到 Discord 应用程序以批准并将您的机器人添加到您的服务器。
现在 Discord 已经整理好了,让我们来看看剩下的技术要求。
安装 Node
安装 node.js 最简单的方法是打开一个新的控制台或终端窗口,然后输入适合您操作系统的命令:
# Download and install fnm: | |
winget install Schniz.fnm # Windows | |
curl -o- https://fnm.vercel.app/install | bash # Linux / Mac | |
# Download and install Node.js: | |
fnm install 22 | |
# Verify the Node.js version: | |
node -v # Should print "v22.14.0". |
如何找到我的加密 API 密钥?
要获取您的 CoinGecko API 密钥,请前往开发者控制面板,然后点击右上角的“+添加新密钥” 。您可以从控制面板更新和管理您的 API 密钥。如果您的密钥被盗,您可以点击“删除密钥”按钮将其删除。
有关生成和设置密钥的完整详细信息,请参阅本指南。
AI 代理将依赖CoinGecko API来检索价格或代币信息,因此强烈建议您手头备有密钥。
创建项目环境
首先创建一个空目录并初始化一个新的 Node 项目:
npm innit -y |
接下来,我们将安装应用程序运行所需的软件包,并初始化 Typescript 设置。
npm install solana-agent-kit typescript ts-node @types/node discord.js | |
npx tsc --innit |
现在项目环境已配置完毕,请继续创建一个空的.env文件,并删除您在上一步中创建的 API、钱包私钥和 RPC URL:
OPENAI_API_KEY="OPENAI_KEY" | |
RPC_URL="RPC_URL" | |
SOLANA_PRIVATE_KEY="WALLET_PRIVATE_KEY" | |
COINGECKO_PRO_API_KEY="COINGECKO_PRO_API_KEY" | |
PERPLEXITY_API_KEY="PERPLEXITY_API_KEY" | |
DISCORD_TOKEN="DISCORD_BOT_TOKEN" |
为了设置我们的 DeFAI 代理,我们将利用SendAI 的 Solana 代理套件,它简化了构建和管理 AI 代理的过程。
该工具包通过自动处理聊天历史记录的存储和检索,消除了许多复杂性,因此我们无需手动管理。它还提供了一个内置的函数调用系统,能够执行多种链上和链下操作。
首先,在项目根目录中创建一个名为agent.ts的新文件。此文件将定义并导出我们的 AI 代理,使其可在整个代码库中访问。
import { SolanaAgentKit, createSolanaTools } from "solana-agent-kit"; | |
import { ChatOpenAI } from "@langchain/openai"; | |
import { createReactAgent } from "@langchain/langgraph/prebuilt"; | |
import { MemorySaver } from "@langchain/langgraph"; | |
import * as dotenv from "dotenv"; | |
import * as bs58 from "bs58"; | |
dotenv.config(); | |
// Ensure the private key is Base58 encoded and decode it if necessary | |
const privateKeyBase58 = process.env.SOLANA_PRIVATE_KEY!; | |
let decodedPrivateKey: Uint8Array; | |
// Attempt to decode the private key to ensure it's in the correct format | |
try { | |
decodedPrivateKey = bs58.default.decode(privateKeyBase58); | |
if (decodedPrivateKey.length !== 64) { | |
throw new Error( | |
"Invalid Solana private key length. It should be 64 bytes." | |
); | |
} | |
} catch (error) { | |
console.error("Error decoding private key:", error); | |
throw error; | |
} | |
// We export this so that we can access CoinGecko through the Agent Kit | |
export const solanaKit = new SolanaAgentKit( | |
privateKeyBase58, | |
process.env.RPC_URL!, | |
{ | |
OPENAI_API_KEY: process.env.OPENAI_API_KEY, | |
COINGECKO_PRO_API_KEY: process.env.COINGECKO_PRO_API_KEY, | |
COINGECKO_DEMO_API_KEY: process.env.COINGECKO_DEMO_API_KEY, | |
PERPLEXITY_API_KEY: process.env.PERPLEXITY_API_KEY, | |
} | |
); | |
export async function initializeAgent() { | |
const llm = new ChatOpenAI({ | |
modelName: "gpt-4o", // Adjust as needed, depending on the model you are using | |
temperature: 0.7, // Adjust the temperature for creativity/variance in responses | |
}); | |
const memory = new MemorySaver(); | |
const config = { configurable: { thread_id: "Solana Agent Kit!" } }; | |
const tools = createSolanaTools(solanaKit); | |
return createReactAgent({ | |
llm, | |
tools, | |
checkpointSaver: memory, | |
}); | |
} |
此设置初始化我们的 AI 代理,并确保在创建 SolanaAgentKit 实例之前正确格式化 Solana 私钥,该实例提供对区块链和 CoinGecko 等 API 服务的访问。
initializeAgent ()函数使用 OpenAI 的 GPT-4o 设置 AI 模型,启用内存存储,配置 Solana 特定工具,并导出代理供我们在应用程序中使用。
如何设置你的 Discord DeFAI 机器人
现在我们已经有了创建代理的方法,接下来需要初始化它,并与 Discord 之间传递消息。一个简单的方法是使用我们之前安装的discord.js包。
首先创建一个名为index.ts的新文件。这将是我们应用程序的入口点。然后我们将导入必要的库并加载dotenv。
import { initializeAgent } from "./agent"; | |
import { HumanMessage } from "@langchain/core/messages"; | |
import { Client, GatewayIntentBits } from 'discord.js'; | |
import dotenv from 'dotenv'; | |
dotenv.config(); |
接下来,我们定义代理的类型并初始化 Discord 客户端,这将帮助我们管理往返于服务器的消息。
// Initialize agent once when bot starts | |
let agent: Awaited<ReturnType<typeof initializeAgent>>; | |
const client = new Client({ | |
intents: [ | |
GatewayIntentBits.Guilds, | |
GatewayIntentBits.GuildMessages, | |
GatewayIntentBits.MessageContent | |
] | |
}); |
我们将初始化 Discord 机器人,确保其启动时会在控制台中记录一条登录成功的确认消息。同时,我们还将初始化 DeFAI 代理,该代理每个机器人会话只需设置一次。
这一点至关重要,因为代理在整个会话过程中都会保留对话记忆。由于其上下文和记忆会在每次初始化时重置,因此务必注意其实例化的时间和方式。
client.on('ready', async () => { | |
console.log(`Logged in as ${client.user?.tag}!`); | |
agent = await initializeAgent(); | |
}); |
现在,剩下要做的就是处理我们机器人的行为以及 Discord 用户消息和 DeFAI 机器人消息之间的交互。
client.on('messageCreate', async (message) => { | |
if (message.author.bot || !message.content.startsWith('!')) return; | |
try { | |
const userInput = message.content.slice(1).trim(); | |
const config = { configurable: { thread_id: message.channel.id } }; | |
if (!agent) { | |
return message.reply("Agent is initializing, please try again in a moment..."); | |
} | |
// Send initial response and typing indicator | |
await message.reply("Processing your request..."); | |
await message.channel.sendTyping(); | |
const stream = await agent.stream( | |
{ messages: [new HumanMessage(userInput)] }, | |
config | |
); | |
let responseContent = ""; | |
for await (const chunk of stream) { | |
let chunkContent = ""; | |
if ("agent" in chunk) { | |
chunkContent = chunk.agent.messages[0]?.content || ""; | |
} | |
if (chunkContent) { | |
await message.reply(chunkContent) | |
} | |
} | |
} catch (error) { | |
console.error("Error during processing:", error); | |
await message.reply("❌ Error processing your request"); | |
} | |
}); |
在这里,我们监听 Discord 服务器中的消息,并处理以“!”开头的用户命令。收到消息后,我们首先确保它不是来自机器人,并且以命令前缀开头。
然后,我们提取用户的输入,使用 Discord 频道 ID 设置配置,并检查 AI 代理是否可用。如果代理尚未初始化,我们将通知用户稍后重试。
代理准备就绪后,我们会通过响应和输入指示来确认请求,然后再流式传输 AI 生成的回复。消息会分块处理,每个块都会作为回复实时发送。如果处理过程中出现错误,我们会记录错误并通知用户其请求无法完成。
最后,让我们登录 Discord 客户端并启动我们的机器人:
client.login(process.env.DISCORD_TOKEN); |
要执行代码,只需从根目录运行ts-node index.ts (或 npx ts-node index.ts)。
机器人将需要几秒钟来初始化,因此在从 Discord 发送命令之前请等待以下日志:以 YourBotName#1111 身份登录!
一旦机器人初始化完毕,您就可以使用自然语言与其进行交流,就像与任何其他 LLM 交流一样,但请记住在发送给 DeFAI 机器人的每条消息前面加上感叹号 (!)。
DeFAI 机器人示例和用例
聊天机器人
对于此机器人,您无需使用特定命令。这意味着其用例受限于机器人在服务器上的权限级别以及 Solana Agent Kit 的内置功能。
首先,这是我要求它向用户打招呼的一个例子:
当然,最好的用例是链上的用例,所以让我们来探索一下。
向用户发送加密货币
代理套件的一个用例是设置社区奖励和激励机制。虽然实现此目的的方法有很多,但一个简单的方法是跟踪钱包地址,并使用您的 Discord DeFAI 代理无缝分发赠品和奖励。
有时,机器人会通过反复试验达到预期的结果。由于代理可以访问 Solana 生态系统中的多项功能,因此它有时可能会难以确定要采取的具体操作或如何正确构建请求。
在这些情况下,机器人会重试该操作,并提示自身纠正任何错误。虽然此工具仅显示代理 响应,但每次调用函数时,都会生成相应的工具响应。这对于在控制台中进行日志记录和调试非常有用,但在 Discord 回复中应避免使用,因为它会使回复过长且杂乱。
追踪用户奖励和交易
DeFAI 机器人的另一个用例是跟踪社区内的交易和奖励分配。需要注意的是,该工具有时可能会对已知的信息产生一些困惑,我发现提醒它通常就能解决问题。
这已经在 GPT-4o 上进行了测试,因此你切换到 o1 可能会获得更好的结果。
获取池信息
DeFAI 代理还可以通过 CoinGecko API 的链上 DEX 数据帮助我们识别当前流行的池和主题。
注意事项
使用 SendAI 的 Solana Agent Kit 等工具部署 Discord DeFAI 机器人时,请优先考虑安全性、可扩展性和社区参与度。
首先,考虑通过实施基于角色的权限或特定渠道的限制,将机器人的命令访问权限限制在授权用户范围内。避免允许不受限制地执行诸如掉期或转账之类的敏感操作,这可能会导致滥用。
为了钱包安全,请使用资金最少的专用钱包代替主钱包,并将其私钥安全地存储在加密环境中。切勿在代码或公共渠道中暴露密钥。为了增强社区参与度,请启用服务器指标权限来跟踪用户活动并自动奖励活跃成员。同时,请结合透明的规则来建立信任。
另一个需要牢记的要点是机器人的上下文。由于其内存在每次初始化时都会重置,因此可以使用外部数据库来保存上下文,并在需要时将其反馈给工具。
最后,请务必记住监控您已验证身份的第三方工具的 API 速率限制,以避免中断和成本增加。