AI+Web3 能做什么?LangChain+DeepSeek 智能决策系统实战解析

  • 木西
  • 发布于 4天前
  • 阅读 98

前言及免责本实例代码及所涉场景仅作为Web3+AI落地应用的技术案例,旨在展示两者结合的实现切入点与思路框架,不构成任何投资建议或交易诱导。代码中涉及的自动化交易策略存在资金损失风险,包括但不限于智能合约漏洞、市场流动性不足、预言机争议及模型决策失误。请勿将本代码直接用于真实资金交易,使

前言及免责

本实例代码及所涉场景仅作为 Web3 + AI 落地应用的技术案例,旨在展示两者结合的实现切入点与思路框架,不构成任何投资建议或交易诱导。代码中涉及的自动化交易策略存在资金损失风险,包括但不限于智能合约漏洞、市场流动性不足、预言机争议及模型决策失误。请勿将本代码直接用于真实资金交易,使用前应充分理解其机制并进行严格的安全审计。作者不对任何基于本代码的操作后果承担责任。

一、预测市场的套利机会

Polymarket 作为全球最大的去中心化预测市场平台,其独特的二元市场结构(YES/NO)天然存在套利空间。在理想状态下,同一事件的 YES 和 NO 代币价格之和应等于 1.0 美元(因为事件必然发生或不发生)。然而,由于市场分割、流动性差异和信息传播延迟,这种平价关系经常出现偏离——这正是自动化套利机器人的狩猎场。

传统量化交易依赖硬编码规则,而本文介绍的系统创新性地引入大语言模型作为决策中枢,让 AI 自主理解策略目标、分析市场数据并执行交易。

二、系统架构设计

2.1 核心组件

我们的系统采用模块化设计,四个核心工具函数构成交易闭环:

// 工具矩阵:感知 → 决策 → 执行
const allTools = [
    searchMarketTool,      // 感知:扫描市场机会
    getWalletBalanceTool,  // 感知:风控检查(防止透支)
    getOrderBookTool,      // 感知:获取买卖深度
    executeOrderTool       // 执行:下单成交
];

关键设计决策

  • 余额前置检查:在每次交易前查询 USDC 余额,避免因余额不足导致的链上交易失败
  • 金额-份数自动换算:Polymarket API 使用"份数"而非金额,系统自动计算 size = total_dollars / price
  • 硬性风控上限:单笔交易金额严格限制在 50 USDC,即使 LLM 被 prompt 注入攻击也无法突破

2.2 LLM 决策层

与传统策略不同,我们使用 DeepSeek-V3 作为推理引擎:

const llm = new ChatOpenAI({ 
    apiKey: process.env.DEEPSEEK_API_KEY,
    configuration: { baseURL: "https://api.deepseek.com" },
    modelName: "deepseek-chat",
    temperature: 0,  // 确定性输出,减少随机交易
});

通过 createOpenAIFunctionsAgent,LLM 获得工具调用能力(Function Calling) 。当接收到策略指令时,AI 会自主决定调用哪些工具、以什么顺序调用,以及如何从工具返回中提取信息。

三、套利策略的工程实现

3.1 市场扫描与机会识别

搜索工具对接 Polymarket 的 Gamma API,提取关键字段:

// 返回结构化的套利分析数据
{
    title: "2024 US Presidential Election",
    markets: [{
        question: "Will Trump win?",
        clobTokenId: "0x...",      // YES 代币 ID
        prices: [0.62, 0.40],       // [YES价格, NO价格]
        outcomes: ["Yes", "No"]
    }]
}

套利信号计算:当 YES价格 + NO价格 ≠ 1.0 时,存在套利空间。例如:

  • YES = 0.62,NO = 0.40 → 总和 1.02 → 存在 2% 溢价
  • 理论上可同时卖出 YES 和 NO,锁定 2% 无风险收益(需考虑手续费)

3.2 订单簿深度分析

获取订单簿不是为了显示,而是为了计算实际可成交的套利空间

const book = await client.getOrderBook(tokenId);
// 分析前2档买卖盘,计算滑点成本

LLM 会评估:当前买一/卖一价差是否足够覆盖 3% 收益门槛?深度是否支持目标仓位?

3.3 安全下单机制

// 三重防护
if (total_dollars > 50) return "拒绝执行:单笔金额严禁超过 50 USDC";
const size = Math.floor(total_dollars / price);
if (size <= 0) return "错误:投入金额不足以购买 1 份";

为什么用限价单而非市价单?

  • Polymarket 采用 CLOB(中央限价订单簿)模型
  • 限价单避免在流动性不足时产生巨大滑点
  • 符合"套利"本质:只有价格达到预期才成交

四、无人值守的运行时架构

4.1 主循环设计

while (true) {
    console.log(`[${new Date().toLocaleTimeString()}] 开始新一轮扫描...`);
    await executor.invoke({ input: strategyGoal });

    // 强制冷却:2分钟观察期
    await new Promise(resolve => setTimeout(resolve, 120000));
}

工程考量

  • API 频率限制:Polymarket API 有速率限制,2分钟间隔平衡了实时性与稳定性
  • Token 成本控制:每次调用都消耗 DeepSeek API 费用,过度频繁的扫描会侵蚀利润
  • 错误恢复:异常时进入 30 秒短休眠,避免错误雪崩

4.2 策略目标的自然语言描述

最精妙的设计在于:策略本身用自然语言描述

startAutoTrading("搜索关于『2024美国大选』的市场,寻找 YES 和 NO 之间价格加总偏离 1.0 太多的套利机会,并执行操作。");

LLM 理解:

  1. 搜索范围:限定在"2024美国大选"主题
  2. 套利逻辑:YES + NO ≠ 1.0 时存在机会
  3. 行动指令:分析后执行交易(隐含收益率>3%和<50刀的风控)

这种声明式策略定义让非技术人员也能调整交易逻辑,无需修改代码。

五、风险与局限

5.1 已实现的风控

风险类型 防护措施
资金风险 单笔50 USDC硬性上限
透支风险 交易前查询链上余额
价格风险 限价单控制成交价格
操作风险 2分钟冷却防止过度交易

5.2 未解决的风险

  • 智能合约风险:Polymarket 合约漏洞可能导致资金损失
  • 预言机风险:事件结果判定争议(如 2024 大选结果争议场景)
  • 流动性风险:小市场订单簿深度不足,理论套利无法实际成交
  • 模型幻觉:LLM 可能误解工具返回的数据格式,导致错误决策

5.3 生产环境建议

  1. 增加模拟交易模式client.postOrder 前增加 dryRun 参数空跑验证
  2. 多签钱包:大额资金改用 Gnosis Safe 多签管理
  3. 实时监控:接入 Telegram/Discord 机器人推送交易通知
  4. 策略回测:用历史订单簿数据验证策略有效性

六、技术栈总结

层级 技术选型 作用
区块链交互 ethers.js Polygon 网络连接、USDC 合约查询
市场数据 @polymarket/clob-client 订单簿获取、下单执行
AI 框架 langchain Agent 编排、工具调用管理
LLM 模型 DeepSeek-V3 策略理解、决策推理
运行时 Node.js + dotenv 环境配置、无限循环守护

七、结语

这个系统展示了LLM Agent 在金融交易领域的应用潜力:不是让 AI "预测"价格(这仍然困难),而是让 AI 理解规则、执行流程、管理风险。在预测市场这种规则明确、数据结构化、套利逻辑清晰的场景中,LLM 的推理能力可以显著降低策略开发门槛。

未来演进方向包括:多市场并行监控、动态调整扫描频率、基于历史胜率的学习优化,以及与其他 DeFi 协议的组合套利(如结合期权、永续合约进行对冲)。

八、补充:示例代码

工具篇

 import { ethers } from "ethers";
import { ClobClient } from "@polymarket/clob-client";
import { z } from "zod";
import dotenv from 'dotenv';
import { DynamicStructuredTool } from "@langchain/core/tools";

dotenv.config();

// --- 初始化驱动 ---
const provider = new ethers.JsonRpcProvider(process.env.POLYGON_RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
const client = new ClobClient(
    "https://clob.polymarket.com", 
    137,
    wallet,
    {
        apiKey: process.env.POLY_API_KEY,
        apiSecret: process.env.POLY_API_SECRET,
        apiPassphrase: process.env.POLY_PASS_PHRASE,
    }
);

// 1. 搜索工具(修正 URL 和数据结构)
const searchMarketTool = new DynamicStructuredTool({
  name: "search_polymarket",
  description: "搜索 Polymarket 市场。返回包含 YES 和 NO TokenID 及价格的市场列表,用于计算套利空间(YES价格 + NO价格 偏离 1.0)。",
  schema: z.object({
    query: z.string().describe("关键词,如 'Election'")
  }),
  func: async ({ query }) => {
    try {
      // 修正后的 Gamma API URL
      const url = `https://gamma-api.polymarket.com{encodeURIComponent(query)}`;
      const response = await fetch(url);
      const data = await response.json();

      // 提取完整的市场对比数据
      return JSON.stringify(data.slice(0, 3).map(event => ({
        title: event.title,
        markets: event.markets.map(m => ({
          question: m.question,
          // 同时返回 YES 和 NO 的 TokenID 供 Agent 对比
          clobTokenId: m.clobTokenId, 
          prices: m.outcomePrices, // 通常 [YES价格, NO价格]
          outcomes: m.outcomes // 通常 ["Yes", "No"]
        }))
      })));
    } catch (error) {
      return `搜索失败: ${error.message}`;
    }
  },
});

// 2. 余额查询工具(新增:防止透支报错)
const getWalletBalanceTool = new DynamicStructuredTool({
    name: "get_wallet_balance",
    description: "查询当前钱包在 Polygon 网络上的 USDC 余额。",
    schema: z.object({}), // 无需参数
    func: async () => {
        try {
            // Polymarket 主要使用 USDC (Polygon 上的地址)
            const usdcAddress = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
            const abi = ["function balanceOf(address) view returns (uint256)"];
            const contract = new ethers.Contract(usdcAddress, abi, provider);
            const balance = await contract.balanceOf(wallet.address);
            return `当前钱包余额: ${ethers.formatUnits(balance, 6)} USDC`;
        } catch (e) {
            return `查询余额失败: ${e.message}`;
        }
    }
});

// 3. 下单工具(修正:金额到份数的换算)
const executeOrderTool = new DynamicStructuredTool({
    name: "execute_polymarket_order",
    description: "在 Polymarket 下达限价单。注意:amount 是你想投入的美元金额,我会自动换算成购买份数。",
    schema: z.object({
        tokenId: z.string().describe("目标的 Token ID"),
        price: z.number().describe("下单价格/赔率 (0.01-0.99)"),
        total_dollars: z.number().describe("准备投入的总美元金额"),
        side: z.enum(["BUY", "SELL"])
    }),
    func: async ({ tokenId, price, total_dollars, side }) => {
        try {
            // 风控:硬性上限
            if (total_dollars > 50) return "拒绝执行:单笔金额严禁超过 50 USDC。";

            // 换算:Polymarket API 需要的是 size (份数)
            // 份数 = 投入金额 / 单价
            const size = Math.floor(total_dollars / price);

            if (size &lt;= 0) return "错误:投入金额不足以购买 1 份。";

            const order = await client.createOrder({
                tokenID: tokenId,
                price: price,
                side: side.toUpperCase(),
                size: size,
            });

            // 重要:如果是第一次测试,可以将下一行改为 return JSON.stringify(order) 进行空跑
            const response = await client.postOrder(order);
            return `订单提交成功!ID: ${response.orderID}, 购买份数: ${size}`;
        } catch (e) {
            return `交易失败: ${e.message}`;
        }
    }
});

// 4. 订单簿查询(保持不变)
const getOrderBookTool = new DynamicStructuredTool({
    name: "get_market_orderbook",
    description: "获取买卖盘深度。",
    schema: z.object({ tokenId: z.string() }),
    func: async ({ tokenId }) => {
        try {
            const book = await client.getOrderBook(tokenId);
            return JSON.stringify({ asks: book.asks.slice(0, 2), bids: book.bids.slice(0, 2) });
        } catch (e) { return `获取深度失败: ${e.message}`; }
    }
});

export const Tools = {
    searchMarketTool,
    getWalletBalanceTool,
    getOrderBookTool,
    executeOrderTool
};

agent执行脚本

 import dotenv from 'dotenv';

import { ChatOpenAI } from "@langchain/openai";
import { AgentExecutor, createOpenAIFunctionsAgent } from "langchain/agents";
import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";
// import { DynamicStructuredTool } from "@langchain/core/tools";
// import { z } from "zod";
dotenv.config();
// import { Tools } from "./tools.js";
// const { searchMarketTool, getOrderBookTool, executeOrderTool } = Tools;
import { Tools } from "./tools1.js";
// AgentExecutor.js 中修改这一行
const { searchMarketTool, getWalletBalanceTool, getOrderBookTool, executeOrderTool } = Tools;

const allTools = [searchMarketTool,getWalletBalanceTool, getOrderBookTool, executeOrderTool].filter(
  (tool) => tool !== undefined
);
// 检查工具数量是否符合预期
if (allTools.length &lt; 4) {
  throw new Error(`工具加载不完整!期望 4 个,实际加载了 ${allTools.length} 个。`);
}

// 定义策略逻辑
async function startAutoTrading(strategyGoal) {
    // --- 1. 定义策略目标 ---
    const prompt = ChatPromptTemplate.fromMessages([
        ["system", `你是一个专业的无人值守套利机器人。
        你的任务是:
        1. 扫描市场。
        2. 分析买卖深度,寻找价格差或不合理的赔率。
        3. 计算预期收益率(需扣除交易成本)。
        4. 只有在收益率 > 3% 且单笔风险 &lt; 50 刀时才下单。
        5. 每一轮操作后,总结你的动作。`],
        ["human", "{input}"],
        new MessagesPlaceholder("agent_scratchpad"),
    ]);
    // --- 2. 配置 DeepSeek 模型 ---
    const llm = new ChatOpenAI({ 
      apiKey: process.env.DEEPSEEK_API_KEY,
      configuration: {
        baseURL: "https://api.deepseek.com",
      },
      modelName: "deepseek-chat",
      temperature: 0,
    });
    const agent = await createOpenAIFunctionsAgent({ llm, tools: allTools, prompt });
    const executor = new AgentExecutor({ agent, tools: allTools, verbose: true });

    console.log("🚀 全自动交易机器人已启动...");

    while (true) {
        try {
            console.log(`\n[${new Date().toLocaleTimeString()}] 开始新一轮扫描...`);

            await executor.invoke({ 
                input: strategyGoal 
            });

            // 强制休眠 2 分钟,防止 API 频率受限或产生过多 token 费用
            console.log("⏳ 扫描结束,进入观察期...");
            await new Promise(resolve => setTimeout(resolve, 120000));
        } catch (error) {
            console.error("❌ 循环中出现异常:", error.message);
            await new Promise(resolve => setTimeout(resolve, 30000)); // 遇到错误休息 30 秒
        }
    }
}

// 启动!
startAutoTrading("搜索关于『2024美国大选』的市场,寻找 YES 和 NO 之间价格加总偏离 1.0 太多的套利机会,并执行操作。");
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
木西
木西
0x5D5C...2dD7
江湖只有他的大名,没有他的介绍。