news 2026/10/10 12:01:29

fuels-ts 中的 @fuel-ts/script 包:Script 调用流程源码解析与完整版本演进

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
fuels-ts 中的 @fuel-ts/script 包:Script 调用流程源码解析与完整版本演进
  • 区块链
  • Web3

【免费下载链接】fuels-ts

Fuel Network Typescript SDK

项目地址:https://gitcode.com/GitHub_Trending/fu/fuels-ts
点击查看免费下载

本篇以@fuel-ts/script包的变更记录(packages/script/CHANGELOG.md)为主线,结合当前仓库源码,讲清这个包在 Fuel Network TypeScript SDK 中的职责边界、Script/ScriptInvocationScope/ScriptRequest三类核心 API 的调用链路、可配置常量与 Blob 部署机制,并完整继承 changelog 中从 2022 年 v0.1.0 到当前 0.103.0 的全部版本里程碑。读完本文,你既能照着仓库测试用例跑通一个带main参数的 Sway script,也能理解每次版本升级(forc、fuel-core、Provider 初始化方式、Node 支持矩阵)对实际使用方的影响。

包定位与项目结构

@fuel-ts/script是 fuels-ts 单体仓库中负责"执行 Sway script 程序"的库包,源码位于packages/script/。从 packages/script/package.json 可以看到当前版本为0.103.0(与 changelog 最新条目一致),运行环境要求node: ^20.0.0 || ^22.0.0 || ^24.0.0,产物同时提供 CJS(dist/index.js)、ESM(dist/index.mjs)与类型声明(dist/index.d.ts)。

它的运行时依赖恰好是 changelog 中反复出现的那批 workspace 兄弟包,这一点对理解 changelog 至关重要——绝大多数版本条目其实是这些依赖包的同步升级:

依赖版本策略
@fuel-ts/abi-coderworkspace:*
@fuel-ts/accountworkspace:*
@fuel-ts/errorsworkspace:*
@fuel-ts/mathworkspace:*
@fuel-ts/programworkspace:*
@fuel-ts/transactionsworkspace:*
@fuel-ts/utilsworkspace:*

devDependencies 中只有@internal/forc(用于编译测试用的 Sway 工程)。构建脚本也很直接:pretest先执行build:forc(pnpm fuels-forc build -p test/fixtures/forc-projects --release),build用 tsup,postbuild执行 scripts/postbuild.ts。

源码文件极少、职责清晰(见 packages/script/src/index.ts 的三个导出):

文件职责
src/script.tsScript类:bytecode + ABI + Account 的封装、setConfigurableConstants、deploy
src/script-invocation-scope.tsScriptInvocationScope:构造ScriptRequest并挂载到ScriptTransactionRequest
src/scripts.tsreturnZeroScript:内置的"返回零"极简脚本,用于纯转账交易
src/types.tsAbstractScript抽象基类(继承自@fuel-ts/program的AbstractProgram,要求实现bytes: Uint8Array)

核心 API:从构造函数到 functions.main

1. Script 类

Script的构造函数接收编译产物(bytecode)、JSON ABI 和一个Account(见 packages/script/src/script.ts#L70-L82):

constructor(bytecode: BytesLike, abi: JsonAbi, account: Account) { super(); this.bytes = arrayify(bytecode); this.interface = new Interface(abi); this.provider = account.provider; // Provider 直接取自 Account this.account = account; this.functions = { main: (...args: TInput) => new ScriptInvocationScope(this, this.interface.getFunction('main'), args), }; }

关键点:

  • provider不是单独传入的,而是从account.provider派生的;这也呼应了 changelog 0.98.0 的 breaking change("makingproviderinitializationsyncagain")——Provider 与 Account 的绑定关系决定了 script 初始化时不需要额外异步操作。
  • functions只暴露main一个入口。这与 Sway script 的语言模型一致:script 没有可被外部选择的函数集,入口固定为main,泛型TInput/TOutput约束了参数与返回值类型。
  • 调用script.functions.main(...args)返回的是一个ScriptInvocationScope,而不是立即发送交易。

2. ScriptInvocationScope 与调用链

packages/script/src/script-invocation-scope.ts 继承自@fuel-ts/program的FunctionInvocationScope,核心是两个方法:

protected override async updateScriptRequest() { if (!this.scriptRequest) { await this.buildScriptRequest(); } this.transactionRequest.setScript(this.scriptRequest, this.args); } private async buildScriptRequest() { const programBytes = (this.program as AbstractScript).bytes; const chainInfoCache = await (this.program.provider as Provider).getChain(); if (!chainInfoCache) { throw new FuelError( FuelError.CODES.CHAIN_INFO_CACHE_EMPTY, 'Provider chain info cache is empty. ...' ); } this.scriptRequest = new ScriptRequest( programBytes, (args: TArgs) => this.func.encodeArguments(args), () => [] as unknown as TReturn ); }

可以推断出完整调用链:functions.main(args)→ScriptInvocationScope→buildScriptRequest()(需要provider.getChain()的缓存,因此 Provider 必须先正确初始化,这正是 changelog 0.58.0 要求Provider.create(url)异步初始化的原因)→transactionRequest.setScript(...)(ScriptTransactionRequest来自@fuel-ts/account)→ 基类BaseInvocationScope的call()。

call()定义在 packages/program/src/functions/base-invocation-scope.ts#L503-L549,它先执行fundWithRequiredCoins(自动估计并填充费用输入),再account.sendTransaction,最终返回:

{ transactionId: string; waitForResult: () => Promise<FunctionResult<T>>; waitForPreConfirmation: () => Promise<PreConfirmationFunctionResult<T>>; }

即提交是"两步式"的:先拿到transactionId,再决定是否waitForResult。结果组装由 packages/program/src/response.ts 中的buildFunctionResult完成——它从 receipts 中提取value(返回值解码)、logs、groupedLogs、gasUsed与transactionId。

3. ScriptRequest:数据偏移与结果解码

ScriptRequest位于 packages/program/src/script-request.ts,承担三件事:

  • 数据偏移计算:getScriptDataOffsetWithScriptBytes(byteLength, maxInputs)用SCRIPT_FIXED_SIZE + calculateVmTxMemory({ maxInputs }) + byteLength计算 script data 在 VM 内存中的起始位置——maxInputs来自链的 consensus parameters,所以这也是"调用前必须拉取 chain info"的底层原因。
  • 参数编码:encodeScriptData(data)支持两种编码器返回形态——直接Uint8Array,或{ data, script }对象(后者允许编码阶段改写脚本字节)。
  • 结果解码:decodeCallResult会遍历 receipts 找ScriptResult与Return/ReturnData/Revertreceipt;遇到Revert时抛出SCRIPT_REVERTED,并由extractTxError结合 logs、receipts、dry-run status 组装出带原因的可读错误——这正是 changelog 0.13.0 起"Failures now output the reason"这条改进在多年后的完整形态。

4. returnZeroScript:内置极简脚本

packages/script/src/scripts.ts 中硬编码了一个 4 字节的脚本,源码注释标明其汇编语义为RET(REG_ZERO); NOOP(字节为0x24000000),"用于 coin 转账交易"。它是 SDK 内部在纯转账场景下构造 script 交易的兜底手段(代码中的 TODO 注明未来应移除硬编码脚本,对应上游 issue #281)。

可配置常量:setConfigurableConstants

changelog 0.43.0 引入了 "add support for configurable constants on scripts"(PR #1003),对应实现是Script的setConfigurableConstants(packages/script/src/script.ts#L91-L122):

setConfigurableConstants(configurables: { [name: string]: unknown }) { try { if (!Object.keys(this.interface.configurables).length) { throw new FuelError( FuelError.CODES.INVALID_CONFIGURABLE_CONSTANTS, `The script does not have configurable constants to be set` ); } Object.entries(configurables).forEach(([key, value]) => { if (!this.interface.configurables[key]) { throw new FuelError( FuelError.CODES.CONFIGURABLE_NOT_FOUND, `The script does not have a configurable constant named: '${key}'` ); } const { offset } = this.interface.configurables[key]; const encoded = this.interface.encodeConfigurable(key, value as InputValue); this.bytes.set(encoded, offset); // 直接把编码值写回字节码 }); } catch (err) { throw new FuelError( FuelError.CODES.INVALID_CONFIGURABLE_CONSTANTS, `Error setting configurable constants: ${(<Error>err).message}.` ); } return this; }

实现方式是把编码后的常量值直接写进脚本字节码中 ABI 声明的 offset 位置(this.bytes.set(encoded, offset)),因此必须在执行前调用。packages/script/src/script.test.ts 中有两条对应的负向用例:脚本没有 configurables 时抛INVALID_CONFIGURABLE_CONSTANTS("The script does not have configurable constants to be set");常量名拼错时抛 "does not have a configurable constant named: 'NOT_DEFINED'"。

部署脚本:deploy() 与 Blob 机制

较新的Script提供deploy方法(packages/script/src/script.ts#L133-L141),底层是@fuel-ts/account的deployScriptOrPredicate(packages/account/src/utils/deployScriptOrPredicate.ts)。其流程为:

  1. 用getBytecodeId(bytecode)计算blobId;
  2. 把去掉 configurables 段的字节码放进BlobTransactionRequest的 witness;
  3. 用getPredicateScriptLoaderInstructions生成一段"loader" 字节码(负责在运行期从 blob 加载完整脚本),并同步调整 ABI 中 configurable 的 offset(adjustConfigurableOffsets);
  4. 先provider.getBlobs([blobId])查询链上是否已存在该 blob——已存在则直接返回 loader 实例,不重复提交;
  5. 否则由部署方钱包出资(assembleTx组装 blob 交易)、sendTransaction提交并等待成功,失败抛TRANSACTION_FAILED;
  6. 返回{ blobId, waitForResult },waitForResult解析出加载后的Script实例。

fuels CLI 的部署命令直接复用了这条链路,见 packages/fuels/src/cli/commands/deploy/deployScripts.ts#L31-L35:

const script = new Script(bytecode, abi, wallet); const { bytes: loaderBytecode, interface: { jsonAbi }, } = await (await script.deploy(wallet)).waitForResult();

部署完成后记录的是loader 字节码 + 调整后的 ABI,后续调用方只需持有这段 loader bytecode 即可,完整脚本体留在链上 blob 中按需加载。

实战:实例化并运行一个 script

仓库内置的端到端示例

packages/script自带 Sway 测试工程 test/fixtures/forc-projects/call-test-script/src/main.sw:

script; struct MyStruct { arg_one: bool, arg_two: u64, } fn main(my_struct: MyStruct) -> MyStruct { log(my_struct.arg_one); log(my_struct.arg_two); MyStruct { arg_one: my_struct.arg_one, arg_two: my_struct.arg_two, } }

对应的测试 packages/script/src/script.test.ts#L55-L98 演示了不经过类型生成(typegen)、手工构造ScriptRequest的"手写封装"路线:

const abiInterface = new Interface(scriptJsonAbi); scriptRequest = new ScriptRequest( scriptBin, (myStruct: MyStruct) => arrayify(abiInterface.functions.main.encodeArguments([myStruct])), (scriptResult) => { if (scriptResult.returnReceipt.type === ReceiptType.Revert) throw new Error('Reverted'); if (scriptResult.returnReceipt.type !== ReceiptType.ReturnData) throw new Error('fail'); const decoded = abiInterface.functions.main.decodeOutput(scriptResult.returnReceipt.data); return (decoded as any)[0]; } ); const request = new ScriptTransactionRequest(); request.setScript(script, data); await request.estimateAndFund(account); const response = await account.sendTransaction(request); const transactionResult = await response.waitForResult(); const result = script.decodeCallResult(transactionResult);

这条路径对应官方文档 apps/docs/src/guide/scripts/running-scripts.md 中 "hand code out a solution wrapper" 的写法;如果你使用fuels typegen生成的类型,则可以走更简洁的new FuelScript(bytecode, abi, wallet)路线,见 apps/docs/src/guide/scripts/instantiating-a-script.md。

使用类型生成后的典型调用

packages/fuel-gauge/src/script-main-args.test.ts 覆盖了带main参数的 script 的多种形态(单参 u8、双参 struct、struct 返回、txParams 校验):

const scriptInstance = new FuelScript<BigNumberish[], BigNumberish>( ScriptMainArgs.bytecode, ScriptMainArgs.abi, wallet ); const { waitForResult } = await scriptInstance.functions.main(foo).call(); const { value, logs, groupedLogs } = await waitForResult(); expect(value?.toString()).toEqual(bn(foo).toString()); expect(logs).toStrictEqual(['u8 foo', 33]); expect(groupedLogs).toStrictEqual({ [ZeroBytes32]: ['u8 foo', 33] });

几个可验证的行为细节:

  • waitForResult()返回对象同时带value、logs、groupedLogs、gasUsed等字段(由 packages/program/src/response.ts#L157-L168 组装);
  • Sway 侧log(...)的输出会按"标签 + 值"成对出现在logs中,并归组到groupedLogs[ZeroBytes32]下;
  • txParams({ gasLimit: 10 })若低于交易需求会直接拒绝,报错匹配/Gas limit '10' is lower than the required/——gas 策略(TX policies)在 changelog 0.70.0/0.71.0 加入(PR #1437/#1624)。

版本演进:changelog 的完整继承与解读

@fuel-ts/script的 changelog 覆盖2022-03-04 的 v0.1.0 到 2026 年的 0.103.0,采用 Conventional Commits 约定(文件尾注"See Conventional Commits for commit guidelines")。下面按时间正序完整列出全部版本及其要义;其中只有依赖同步的补丁版本统一标注"依赖同步"。

2022 年:v0.1.0 → v0.7.0

版本日期要义
v0.1.02022-03-04首个版本
v0.3.02022-03-04版本推进
v0.4.02022-03-13版本推进
v0.5.02022-03-30版本推进
v0.6.02022-04-25版本推进
v0.7.02022-06-02启用 UTXO 校验(PR #278)

0.8.0 → 0.18.0:工具链与数字类型奠基

版本类型要义
0.8.0Minor全包 bump minor(PR #405);新增 README(#374);修复 fuels 包列表(#397)
0.9.0Patch依赖同步
0.10.0Minor从 providers 包移除 transactions 再导出(PR #428)
0.11.0Patch修复包链接到node_modules内部的问题、移除旧 Lerna 配置(PR #437)——monorepo 从 Lerna 迁移的印记
0.12.0Patch依赖同步
0.13.0Minor失败现在会输出原因(PR #456)
0.14.0Patch依赖同步
0.15.0Patch用 bn.js 重构替代原生 bigint(PR #468)——@fuel-ts/math的bn自此贯穿 SDK
0.16.0Minor修复ByteArrayCoder导入(PR #509)
0.17.0Minor升级forc到 0.24.3(#511);解析 Logs 与 Log Data(PR #517)
0.18.0Patch依赖更新(#543);全仓库forc fmt格式化(#535)

0.19.0 → 0.33.0:Account 化与 main 参数

版本类型要义
0.19.0Minor交易增加 output 变量(PR #549)
0.20.0–0.22.1Patch依赖同步(0.22.2 增加文档与示例 #612)
0.23.0Patch文档更新(#639);revert/失败时改进日志输出(PR #640)
0.24.0–0.28.1Patch依赖同步(0.24.2 调整文档更新时序 #646)
0.29.0Patch库导出与测试工具分离(PR #709);新增 scripts 文档(PR #670)
0.30.0–0.31.0Patch依赖同步
0.32.0MinorBaseWalletLocked更名Account后的全量适配(PR #789)——账户模型统一的节点
0.33.0Minorscript 支持 main 参数(PR #745)——functions.main(...args)用法的确立

0.34.0 → 0.58.0:ABI 现代化

版本类型要义
0.35.0Patch调整所有包的导出字段(PR #819)
0.36.0Minor删除@fuel-ts/constants包,常量迁移到各包<package>/configs,并由fuels伞包统一导出(PR #820)
0.37.0–0.37.1Patch依赖同步
0.38.0Minor文档引擎从 Jekyll 切换到 VitePress(PR #811)——当前apps/docs的来历
0.38.1Patch依赖同步
0.39.0Minorabi-coder 重构:编解码移入FunctionFragment;指针类型也携带选择器/签名信息(PR #891)
0.40.0–0.42.0Patch依赖同步
0.43.0Minorscript 支持 configurable constants(PR #1003)
0.44.0Minor全量重构包配置、支持本地安装(PR #984)
0.45.0–0.45.xPatch依赖同步
0.46.0MinorScriptTransactionRequest可用性与文档改进(PR #1072);forc-bin发布形态调整(#1073);用.d.ts+ declaration map 替代publishConfigs(#1055)
0.47.0Minor清除旧版 ABI 格式(PR #1094);改进 Vector 支持(PR #1046)
0.48.0PatchNativeAssetId更名BaseAssetId,与 Rust SDK 对齐(PR #1121)
0.48.2Patch弃用 tx funding call 选项——所有交易都要求 spendable input(PR #1136)
0.49.0–0.50.0Patch依赖同步
0.51.0Minor升级fuel-core到 0.20.3(PR #1112)
0.52.0–0.57.0Minor/Patch版本推进(无独立变更描述)
0.58.0MinorchainInfo在 Provider 初始化时拉取并缓存,需改为await Provider.create(url);Predicate构造移除chainId;全量改用FuelError(PR #1181、#1230)

0.59.0 → 0.86.0:CLI、策略与节点/编译器升级

版本类型要义
0.63.0Patch清除 ethers v5 的arrayify,改用 ethers v6 的getBytes(PR #1255)
0.64.0–0.66.0Patch版本推进(0.66.1 调整包管理器配置 #1415)
0.67.0Minor修复交易出资(funding)问题(PR #1372)
0.68.0Patch标准化所有 forc 工程、修复 turbo 缓存、降低pretest噪音(PR #1442)
0.69.0–0.70.1Minor/Patch版本推进
0.70.0 / 0.71.0Minoru8/bool 按 small bytes 右对齐编解码;新增pnpm create fuelsCLI(对应packages/create-fuels);TX policies 支持(PR #1437/#1565、#1624)
0.72.0–0.72.xPatch版本推进
0.73.0Patchforc升级到 0.49.2(PR #1707)
0.74.0MinorAccount 相关包重构(PR #1675)
0.75.0Patch使用内部工具替代 ethers 的arrayify/hexlify/concat/BytesLike(PR #1775)——摆脱 ethers 字节工具的里程碑
0.76.0–0.82.0Patch/Minor版本推进(0.81.0 引入 knip 依赖检查 #37743e8)
0.83.0Minorforc0.56.0;fuel-core0.24.3;base asset ID 从链上获取(不再硬编码)
0.84.0Minorfuel-core升级到 0.26.0
0.85.0Patch依赖同步
0.86.0Minorforc升级到 0.58.0 并移除V0编码(breaking)

0.87.0 → 0.98.0:统一错误与 Provider 同步化

版本类型要义
0.87.0–0.93.0Patch依赖同步
0.94.0Patch错误体系统一:Error全面切换为FuelError(751d638)
0.94.1–0.94.9Patch依赖同步(0.94.7 修复导出类型 80df900)
0.95.0–0.96.0Patch依赖同步
0.97.0–0.97.2Patch依赖同步(0.97.1 增加noImplicitOverride编译选项 c904a98;注意从 0.98.0 起@fuel-ts/interfaces不再出现在依赖列表中,因该包被重新分配/移除)
0.98.0Minorprovider初始化重新变回同步(458b7cf,breaking);文档优化前端应用(13977df);@fuel-ts/interfaces包重新分配(0b4c3ab);清理无用依赖并更新 knip 配置(68ef74d)

0.99.0 → 0.103.0:当前版本

版本要义
0.99.0依赖同步(16 项上游变更)
0.100.0–0.100.6依赖同步
0.101.0–0.101.3依赖同步
0.101.2支持 Node 24,弃用 Node 18(8c19d93)——与 package.json 中engines: ^20 \|\| ^22 \|\| ^24互相印证
0.102.0依赖同步(4 项上游变更)
0.103.0当前版本,依赖同步(014a606)

如何阅读这份 changelog

三个可复用的规律:

  1. 版本号与依赖同步:monorepo 用 changesets 管理,account、program、abi-coder、errors、math、transactions、utils任一包变更都会驱动@fuel-ts/script出 patch 版,因此 "Updated dependencies" 条目远多于功能条目;升级时建议以fuels伞包版本为准统一升级。
  2. !标记与 "Minor Changes" 代表 breaking change,历史上真正影响使用方式的共五处:0.36.0(constants 包删除)、0.58.0(Provider 必须异步create)、0.70.0/0.71.0(TX policies)、0.83.0/0.84.0/0.86.0(节点与编译器大版本、移除 V0 编码)、0.98.0(Provider 初始化重新同步化)。
  3. 编译器/节点升级驱动了 Sway 工程兼容:forc从 0.24.3(0.17.0)→ 0.49.2(0.73.0)→ 0.56.0(0.83.0)→ 0.58.0(0.86.0),fuel-core从 0.20.3(0.51.0)→ 0.24.3(0.83.0)→ 0.26.0(0.84.0)。仓库内fuel-toolchain.toml(如 apps/create-fuels-counter-guide/fuel-toolchain.toml)与 internal/forc、internal/fuel-core 锁定了测试环境的工具链版本,可据此核对本地forc build产物与 SDK 的兼容区间。

环境要求与适用前提

  • Node:^20.0.0 || ^22.0.0 || ^24.0.0(自 0.101.2 起不再支持 Node 18);
  • 安装:作为 npm 包@fuel-ts/script安装,日常开发通常直接安装伞包fuels并从fuels导入Script(fuel-gauge 测试即如此,如 packages/fuel-gauge/src/script-main-args.test.ts#L1-L3 的import { bn, Script as FuelScript, ZeroBytes32 } from 'fuels');
  • 前提:调用前Account必须已绑定正确初始化的Provider(provider.getChain()缓存非空,否则buildScriptRequest抛CHAIN_INFO_CACHE_EMPTY);
  • 只读说明:本文所有路径均可在当前仓库中直接查看,运行本包测试需先执行pnpm build:forc编译test/fixtures/forc-projects下的 Sway 工程。

小结与延伸阅读路径

@fuel-ts/script包体量小但卡住了 "Sway 字节码 → VM 内存布局 → 交易发送 → 结果解码" 的关键路径:Script负责字节码与常量注入,ScriptInvocationScope负责把编码后的main参数挂进ScriptTransactionRequest,ScriptRequest负责偏移计算与解码,最终由BaseInvocationScope.call()提交并交付waitForResult。结合 2022 年至今的 changelog 可以看到,这个包的变化主要是被 Provider 生命周期(0.58.0/0.98.0)、ABI 与编码体系(0.39.0/0.47.0)、数字类型(0.15.0)、错误体系(0.58.0/0.94.0)与 Node 支持矩阵(0.91.0/0.101.2)这几条主线牵引的。

进一步阅读建议按此顺序:

  1. packages/script/src/script.ts ——Script全量实现;
  2. packages/script/src/script.test.ts 与 test/fixtures/forc-projects/call-test-script/src/main.sw —— 可运行的最小闭环;
  3. packages/program/src/script-request.ts 与 packages/program/src/functions/base-invocation-scope.ts —— 调用与费用组装机制;
  4. packages/account/src/utils/deployScriptOrPredicate.ts —— Blob 部署原理;
  5. apps/docs/src/guide/scripts/ —— 官方脚本使用指南(实例化、运行、日志、可配置常量、部署)。
  • 区块链
  • Web3

【免费下载链接】fuels-ts

Fuel Network Typescript SDK

项目地址:https://gitcode.com/GitHub_Trending/fu/fuels-ts
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 11:59:10

带钢表面缺陷检测数据集:XML标注转YOLO格式实战与避坑指南

简介&#xff1a;YOLO目标检测可直接使用的带钢表面缺陷数据集&#xff0c;面向计算机、电子信息工程、数学等专业学生&#xff0c;适用于课程设计、期末大作业与毕业设计。资源包含1800张带钢表面缺陷图像及对应XML标注文件&#xff0c;并附BMP格式图像副本和1个数据库文件&am…

作者头像 李华
网站建设 2026/10/10 11:57:17

动态图神经网络用于异常流量检测实战

简介&#xff1a;本资源是一套面向计算机科学与人工智能专业高年级本科生、研究生及网络安全工程师的毕业设计级实战项目&#xff0c;聚焦动态图神经网络&#xff08;DGNN&#xff09;在实时异常流量检测中的落地应用。资源完整覆盖从理论建模、代码实现到实验验证的全链路&…

作者头像 李华
网站建设 2026/10/10 11:56:37

句向量过时论可以休矣:2.5亿下载量就是最好的反驳

句向量过时论可以休矣&#xff1a;2.5亿下载量就是最好的反驳 【免费下载链接】all-MiniLM-L6-v2 项目地址: https://ai.gitcode.com/hf_mirrors/sentence-transformers/all-MiniLM-L6-v2 "大模型时代&#xff0c;谁还用句向量&#xff1f;直接让 LLM 把整段文本塞…

作者头像 李华
网站建设 2026/10/10 11:55:36

PHP与ThinkPHP区别详解:语言与框架的定位、选型与实战指南

前端同事有天突然问我&#xff1a;“ThinkPHP 和 PHP 到底啥区别&#xff1f;”他以为 ThinkPHP 是 PHP 的一个新版本&#xff0c;就像 PHP 8 比 PHP 7 更新一样。我当时一愣&#xff0c;但回头翻翻网上提问&#xff0c;这么想的人还真不少——甚至有些做过一两个 PHP 项目的朋…

作者头像 李华
网站建设 2026/10/10 11:54:30

SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0在线考试系统设计与实现全解析

上个月朋友拿一个在线考试的项目需求来找我&#xff0c;说要做一套能同时支持学生在线答题、教师管理题库、自动批改客观题的Web系统。我当时直接给的组合就是SpringBoot2 Vue3 MyBatis-Plus MySQL8.0。这套技术栈在Java Web项目里几乎算是毕业设计、内部管理系统、中小型业…

作者头像 李华