news 2026/9/4 19:50:29

Delphi AI开发实战:基于TMS AI Studio源码的集成、定制与应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Delphi AI开发实战:基于TMS AI Studio源码的集成、定制与应用

简介:本资源是面向Delphi 11–13 Florence版本开发者的AI功能集成工具包——TMS AI Studio v1.3.0.0完整源码版,专为缺乏AI底层经验但熟悉Delphi快速开发的中高级开发者设计,解决在传统桌面/跨平台应用中便捷嵌入图像识别、自然语言处理与机器学习能力的痛点。压缩包共216个文件,含68个Pascal源文件(核心控件逻辑)、32个DPROJ工程配置(适配多版本Delphi)、23个DPR主程序入口、9个DFM/FMX界面定义及8个RES资源文件,辅以说明文档(PDF/MD)、示例数据库(sample.db)与启动脚本(movefiles.bat),整体大小61.44MB。已有111人下载学习,可直接编译运行全部示例(如Uaisimple.dfm、Uaiweather.dfm等),深入理解AI控件封装机制;完整源码支持二次定制、调试追踪与算法模块替换,显著降低Delphi场景下AI工程落地门槛。

1. 项目概述:一份来自社区的“硬核”资源

最近在Delphi开发者圈子里,一个名为“TMS AI Studio v1.3.0.0 for Delphi 11-13 Florence Full Source.rar”的压缩包文件引起了不小的讨论。从文件名就能看出它的分量:这是一个由知名第三方组件厂商TMS Software出品的AI集成开发套件,版本号v1.3.0.0,支持从Delphi 11 Alexandria到最新的Delphi 12 Athens(项目标题中的“13 Florence”可能指代社区对Delphi 12的早期内部代号或误称),并且最关键的是——它附带“Full Source”,即完整源代码。

对于任何一位深耕Delphi生态的开发者来说,这都像是一份从天而降的“宝藏”。TMS的组件向来以高质量和稳定性著称,但通常以编译后的二进制包形式授权分发。能拿到其核心产品TMS AI Studio的完整源代码,意味着你不仅可以无限制地使用这套强大的AI工具集,更能深入其内部,理解每一行代码的实现逻辑,进行定制化修改,甚至学习顶尖组件厂商的架构设计。这不仅仅是获得了一个工具,更是拿到了一本“武功秘籍”。无论是想快速为自家应用注入AI能力(如智能文本分析、图像识别),还是希望研究大型VCL/FireMonkey组件库该如何组织,这个资源都具有极高的参考价值。当然,随之而来的也是关于版权、版本兼容性以及如何正确“消化”这份资源的现实挑战。

2. TMS AI Studio 核心价值与功能模块解析

2.1 为什么是TMS AI Studio?

在Delphi的第三方组件生态中,TMS Software是毫无争议的巨头之一。他们的产品线覆盖了UI控件、报表、图表、ORM、云连接等几乎所有领域。TMS AI Studio则是他们面向人工智能浪潮推出的战略级产品。与网络上零散的、基于某个特定AI接口(如只封装了OpenAI ChatGPT)的组件不同,TMS AI Studio是一个统一的、可扩展的AI能力集成框架

它的核心价值在于抽象与整合。它将不同AI服务提供商(如OpenAI、Google AI、Hugging Face、本地运行的Ollama等)的API,以及不同的AI任务类型(聊天补全、文本嵌入、图像生成、语音识别等),封装成一套统一的、基于Delphi接口的组件。开发者无需关心底层是调用HTTP REST API还是本地DLL,只需在设计时拖放TMSAITMSAIChatTMSAIImage等控件,设置好Provider(供应商)和模型参数,就能以一致的编程模式调用AI功能。这极大地降低了在Delphi应用中集成AI的门槛和复杂度。

2.2 主要功能模块拆解

拥有完整源代码,我们可以清晰地看到其架构。通常,TMS AI Studio会包含以下几个核心模块:

  1. 核心接口与抽象层 (TMS.AI.Core):这是整个库的基石。它定义了IAIProviderIAIChatIAIImage等核心接口,以及TAIRequestTAIResponse等通用数据模型。所有具体的AI服务实现都是这些接口的派生。这种设计遵循了“依赖倒置”原则,使得上层应用代码依赖于抽象接口,而非具体实现,从而轻松切换AI服务商。

  2. 提供商实现层 (TMS.AI.Providers):这个目录下包含了针对各个AI服务的具体实现。例如:

    • TMS.AI.Provider.OpenAI.pas: 封装OpenAI的GPT系列、DALL-E等模型的API调用。
    • TMS.AI.Provider.GoogleAI.pas: 封装Google Gemini API的调用。
    • TMS.AI.Provider.Ollama.pas: 封装与本地Ollama服务(用于运行Llama2、Mistral等开源模型)的通信。
    • 可能还有TMS.AI.Provider.AzureTMS.AI.Provider.Claude等。每个Provider单元都负责处理身份验证、网络请求、错误处理以及将服务商特有的响应格式转换为库定义的通用格式。
  3. 可视化控件层 (TMS.AI.Components):这是提供给开发者在IDE表单上直接拖放使用的控件。例如:

    • TMSAI: 主控件,用于配置全局的API密钥、默认提供商等。
    • TMSAIChat: 专门用于聊天对话场景,管理对话历史、发送消息、流式接收回复。
    • TMSAIImage: 用于图像生成或图像理解任务。
    • TMSAITranscription: 用于语音转文字。
    • 这些控件在内部会创建并管理对应的Provider实例,将属性设置和事件调用桥接到核心API上。
  4. 工具与辅助单元:包括用于处理JSON序列化/反序列化(因为大部分AI API使用JSON)、异步任务管理、日志记录、本地缓存(用于存储嵌入向量或对话历史)等功能的辅助单元。

注意:分析源代码时,要特别注意其网络请求库的选择(是使用Indy、NetHTTPClient还是其他)、异步处理模型(是基于线程、匿名线程还是使用System.Threading),以及错误处理机制。这些是评估其稳定性和性能的关键。

3. 从源代码到可用组件库的完整构建指南

拿到一个.rar格式的完整源代码包,直接使用是不行的。我们需要将其编译、安装到Delphi的IDE中,或者至少将其编译为可供项目引用的DCU/BPL文件。以下是基于常见实践的标准化步骤。

3.1 环境准备与源代码审视

首先,确保你的开发环境符合要求。根据文件名,它支持Delphi 11-13。建议使用Delphi 12 Athens进行尝试,因为其兼容性最好。你需要准备好对应版本的IDE。

解压“TMS AI Studio v1.3.0.0 for Delphi 11-13 Florence Full Source.rar”后,不要急于打开所有文件。先花时间浏览目录结构。一个规范的TMS源码包通常包含以下关键文件/目录:

  • Source\: 核心源代码目录,里面按模块分文件夹。
  • Demos\: 示例程序,这是学习如何使用该库的最佳资料。
  • Packages\: 包含各种版本的DPK(Delphi Package)项目文件,用于编译和安装。
  • Readme.txtInstall.txt: 安装说明(如果有的话,但社区资源往往缺失)。
  • License.txt: 许可协议(**必须仔细阅读!**社区分享的完整源码可能涉及版权风险,仅限个人学习研究)。

第一步:寻找入口点。进入Packages文件夹,你会看到类似TMSAIStudio_D12.dproj(Delphi项目文件)和TMSAIStudio_D12.dpk(包文件)的文件。D12代表Delphi 12。找到与你IDE版本匹配的文件。

3.2 编译与安装的详细步骤

这里以在Delphi 12中安装运行时包(Runtime Package)和设计时包(Design-Time Package)为例。运行时包包含核心功能代码,设计时包负责在IDE工具栏注册控件。

  1. 设置库路径(Library Path):在安装前,最好先将源码路径添加到IDE的库路径中。打开Delphi,点击Tools -> Options -> Language -> Delphi Options -> Library。在Library path中,添加你的源码根目录(例如D:\Components\TMSAIStudio\Source)。这能确保编译器在编译时能找到所有依赖的单元。

  2. 编译运行时包:在IDE中打开Packages目录下的TMSAIStudio_D12.dpk文件。在项目管理器(Project Manager)中,右键点击该包,选择“Compile”。如果编译成功,会在输出目录(通常是.\Bin)生成TMSAIStudio_D12.bpl(运行时包)和.dcu文件。如果编译失败,需要根据错误信息排查。

    • 常见错误1:缺少依赖单元。错误信息可能提示找不到Vcl.ControlsSystem.JSON等。这通常是因为项目搜索路径未包含Delphi标准库路径,但标准包一般不会出现此问题。更可能的是缺少TMS自家的其他依赖包,比如TMS的核心库TMS.Comm.Base等。你需要确认这个AI Studio包是否依赖其他TMS组件,并确保那些组件的源码或DCU路径也在库路径中。
    • 常见错误2:版本不兼容语法。例如,源代码中使用了Delphi 12的新特性,而你的环境是Delphi 11。这时需要根据错误行进行语法降级调整,或者寻找对应Delphi 11版本的包文件。
  3. 安装设计时包:编译通过后,在项目管理器中,右键点击TMSAIStudio_D12.dpk,这次选择“Install”。这个操作会将设计时包注册到IDE。如果安装成功,IDE会提示“Package xxxx has been installed”,并且在工具栏的“TMS”或“AI”分类下,你应该能看到TMSAITMSAIChat等控件图标。

  4. 备用方案:仅使用DCU文件:如果安装过程复杂或总失败,可以采用更轻量的方式。不执行“Install”,只“Compile”。编译成功后,将生成的.dcu文件(分散在Source各子目录下)全部复制到一个统一的目录(如.\DCU)。然后,在你的应用程序项目中,通过Project -> Options -> Delphi Compiler -> Unit scope names或直接在该项目的搜索路径中添加这个.\DCU目录。这样,你就可以在代码中uses相关的AI单元来编程调用,只是无法在表单设计器上拖放控件。

3.3 验证安装与跑通第一个Demo

安装成功后,创建一个新的VCL Application项目。在工具栏找到TMS AI控件,拖一个TMSAITMSAIChat到表单上。查看TMSAI控件的属性,找到Provider属性,将其设置为OpenAI(或其他你配置好的提供商)。然后在TMSAI控件的属性中填入你的API密钥(注意:为了安全,永远不要将硬编码的API密钥提交到版本控制系统,应使用环境变量或配置文件)。

接下来,打开Demos文件夹,找一个最简单的聊天Demo(例如ChatDemo)打开并运行。这是验证整个库是否正常工作的最快方式。运行Demo,输入消息,看是否能收到AI的回复。如果Demo运行成功,说明从源码到编译安装的整个链条是通的。

4. 核心功能实战:构建一个智能文本分析工具

为了深入理解TMS AI Studio的使用,我们抛开Demo,从头构建一个实用的工具:一个本地文档智能摘要与问答工具。它将支持加载文本文件,利用AI生成摘要,并允许用户就文档内容进行提问。

4.1 界面设计与控件布局

我们使用VCL框架。在表单上放置以下控件:

  • TMemo(命名为MemoSource): 用于显示和编辑原始文档文本。
  • TButton(命名为BtnLoadFile): 点击后打开文件对话框加载.txt文件到MemoSource
  • TMSAI(命名为AI): 全局AI控制器。设置其ProviderOllama(假设我们在本地运行了Ollama和Llama2模型),在OnCreate事件中设置其BaseURLhttp://localhost:11434(Ollama默认地址)。
  • TMSAIChat(命名为AIChat): 将其AI属性指向AI控件。这是我们与模型交互的核心。
  • TButton(命名为BtnSummarize): 点击后触发摘要生成。
  • TMemo(命名为MemoSummary): 显示生成的摘要。
  • TEdit(命名为EditQuestion): 用于输入关于文档的问题。
  • TButton(命名为BtnAsk): 点击后提交问题。
  • TMemo(命名为MemoAnswer): 显示AI对问题的回答。

4.2 关键代码实现与逻辑

1. 摘要生成功能:

procedure TFormMain.BtnSummarizeClick(Sender: TObject); var Prompt: string; begin if MemoSource.Text.Trim.IsEmpty then begin ShowMessage('请先加载文档内容。'); Exit; end; // 构建一个指令清晰的Prompt Prompt := '请为以下文本生成一个简洁、准确的摘要,突出核心内容。文本内容如下:' + sLineBreak + sLineBreak + MemoSource.Text; // 设置聊天角色和消息。我们使用“系统”消息来设定AI行为,“用户”消息传递文本。 AIChat.ClearMessages; AIChat.Messages.AddRole(TMessageRole.System).Content := '你是一个专业的文本分析助手,擅长生成简洁的摘要。'; AIChat.Messages.AddRole(TMessageRole.User).Content := Prompt; MemoSummary.Lines.Text := '正在生成摘要,请稍候...'; BtnSummarize.Enabled := False; // 异步调用,避免界面卡死 AIChat.ExecuteAsync( procedure begin // 此回调在AI响应完成后,在主线程中执行 TThread.Synchronize(nil, procedure begin MemoSummary.Lines.Text := AIChat.Messages.Last.Content; BtnSummarize.Enabled := True; end); end, procedure (const Error: string) begin // 错误处理回调 TThread.Synchronize(nil, procedure begin MemoSummary.Lines.Text := '摘要生成失败:' + Error; BtnSummarize.Enabled := True; end); end ); end;

2. 文档问答功能:这个功能的关键在于将文档内容作为“上下文”提供给AI。对于长文档,我们需要使用“嵌入”或“上下文窗口”技术。这里演示一个简单版,将整个文档(假设不长)作为上下文附加到每个问题中。

procedure TFormMain.BtnAskClick(Sender: TObject); var Question: string; ContextPrompt: string; begin Question := EditQuestion.Text.Trim; if Question.IsEmpty then Exit; // 将文档内容作为上下文与问题一起发送 ContextPrompt := '请根据以下文档内容回答问题。如果文档中没有明确答案,请说明“根据提供文档,无法找到相关信息”。' + sLineBreak + sLineBreak + '【文档内容开始】' + sLineBreak + MemoSource.Text + sLineBreak + '【文档内容结束】' + sLineBreak + sLineBreak + '问题:' + Question; AIChat.ClearMessages; // 可以保留一个系统角色设定 AIChat.Messages.AddRole(TMessageRole.System).Content := '你是一个严谨的文档分析员,只根据提供的文档内容回答问题。'; AIChat.Messages.AddRole(TMessageRole.User).Content := ContextPrompt; MemoAnswer.Lines.Text := '正在思考...'; BtnAsk.Enabled := False; AIChat.ExecuteAsync( procedure begin TThread.Synchronize(nil, procedure begin MemoAnswer.Lines.Text := AIChat.Messages.Last.Content; BtnAsk.Enabled := True; end); end, procedure (const Error: string) begin TThread.Synchronize(nil, procedure begin MemoAnswer.Lines.Text := '回答失败:' + Error; BtnAsk.Enabled := True; end); end ); end;

实操心得:在实际使用中,直接将长文档作为上下文会很快耗尽模型的Token限制(通常4K-128K)。对于生产环境,更优的做法是:

  1. 文档分块:将长文档按段落或固定大小分割成多个片段。
  2. 向量化与检索:使用TMS AI Studio的文本嵌入功能(如果该版本支持),将每个片段转换为向量,并存入向量数据库(如Chroma、Qdrant)。
  3. 语义检索:当用户提问时,将问题也向量化,在向量数据库中检索出最相关的几个文档片段。
  4. 构建Prompt:只将这些相关片段作为上下文发送给大模型生成答案。这就是经典的RAG(检索增强生成)架构。TMS AI Studio的完整源码为我们实现这套流程提供了底层API支持。

5. 深度定制与源码学习:修改Provider以适配国产大模型

拥有完整源代码的最大优势在于定制。假设公司要求接入一个国产大模型,如智谱AI、文心一言或通义千问,而TMS AI Studio官方并未提供该Provider。这时,我们就可以自己动手,丰衣足食。

5.1 创建自定义Provider的步骤

  1. 研究现有Provider:打开TMS.AI.Provider.OpenAI.pasTMS.AI.Provider.Ollama.pas,这是最好的模板。你会发现它们都继承自一个基类(例如TCustomAIProvider),并实现了IAIProviderIAIChat等核心接口。

  2. 创建新单元:在Source目录下(或你自己的组件目录),新建一个单元文件,例如TMS.AI.Provider.ZhiPu.pas

  3. 定义Provider类

    unit TMS.AI.Provider.ZhiPu; interface uses System.Classes, System.SysUtils, TMS.AI.Core; // 引用核心单元 type TZhiPuAIProvider = class(TCustomAIProvider, IAIProvider, IAIChat) private FApiKey: string; FBaseURL: string; // 其他私有字段,如HTTP客户端 protected // 实现IAIChat接口的方法 function GetChatCompletion(const ARequest: TAIChatCompletionRequest): TAIChatCompletionResponse; override; procedure GetChatCompletionAsync(const ARequest: TAIChatCompletionRequest; const OnResponse: TProc<TAIChatCompletionResponse>; const OnError: TProc<string>); override; // 可能还需要实现IAIImage, IAIEmbedding等接口的方法 public constructor Create(AOwner: TComponent); override; // 发布必要的属性,如ApiKey, BaseURL property ApiKey: string read FApiKey write FApiKey; property BaseURL: string read FBaseURL write FBaseURL default 'https://open.bigmodel.cn/api/paas/v4/'; end; implementation uses System.Net.HttpClient, System.Net.URLClient, System.JSON; // 可能需要HTTP和JSON单元 constructor TZhiPuAIProvider.Create(AOwner: TComponent); begin inherited; FBaseURL := 'https://open.bigmodel.cn/api/paas/v4/'; end; function TZhiPuAIProvider.GetChatCompletion(const ARequest: TAIChatCompletionRequest): TAIChatCompletionResponse; var LHttpClient: THTTPClient; LRequestStream: TStringStream; LResponseStream: TStringStream; LUrl: string; LJsonReq, LJsonResp: TJSONObject; LMsgArray: TJSONArray; LMsg: TMessage; begin Result := TAIChatCompletionResponse.Create; LHttpClient := THTTPClient.Create; LRequestStream := TStringStream.Create('', TEncoding.UTF8); LResponseStream := TStringStream.Create('', TEncoding.UTF8); try // 1. 构建符合智谱API要求的JSON请求体 LJsonReq := TJSONObject.Create; try LJsonReq.AddPair('model', 'glm-4'); // 指定模型 LMsgArray := TJSONArray.Create; for LMsg in ARequest.Messages do begin LMsgArray.AddElement(TJSONObject.Create .AddPair('role', LMsg.Role.ToString.ToLower) // 注意角色名称可能需转换 .AddPair('content', LMsg.Content)); end; LJsonReq.AddPair('messages', LMsgArray); LJsonReq.AddPair('stream', TJSONBool.Create(False)); LRequestStream.WriteString(LJsonReq.ToJSON); finally LJsonReq.Free; end; // 2. 配置HTTP请求 LUrl := FBaseURL + 'chat/completions'; LHttpClient.CustomHeaders['Authorization'] := 'Bearer ' + FApiKey; LHttpClient.ContentType := 'application/json'; // 3. 发送同步请求 LHttpClient.Post(LUrl, LRequestStream, LResponseStream); // 4. 解析智谱API的响应,并填充到通用的TAIChatCompletionResponse中 LJsonResp := TJSONObject.ParseJSONValue(LResponseStream.DataString) as TJSONObject; try if Assigned(LJsonResp) and LJsonResp.TryGetValue('choices', LMsgArray) and (LMsgArray.Count > 0) then begin Result.Choices.Add(TMessage.Create); Result.Choices.Last.Role := TMessageRole.Assistant; Result.Choices.Last.Content := LMsgArray.Items[0].GetValue<string>('message.content'); end else begin raise Exception.Create('Invalid response from ZhiPu AI: ' + LResponseStream.DataString); end; finally LJsonResp.Free; end; finally LRequestStream.Free; LResponseStream.Free; LHttpClient.Free; end; end; // GetChatCompletionAsync的实现类似,但需使用异步HTTP调用,这里省略... end.
  4. 注册Provider:为了让TMSAI控件能在设计时选择你的ZhiPu提供商,你需要在Provider单元的最后,调用RegisterProvider过程(如果库提供了这样的机制),或者在控件初始化时手动将你的Provider类添加到工厂中。具体方法需要参考源码中其他Provider是如何被注册的,通常在一个TMS.AI.Providers.pasTMS.AI.Register.pas的单元里。

5.2 源码学习的要点

通过这个自定义过程,你能深入学习到:

  • 网络层封装:库是如何抽象HTTP客户端,处理超时、重试和错误的。
  • 数据模型转换:如何将通用的TAIRequest转换为特定厂商的API格式,又如何将厂商的响应转换回来。这是适配器的经典应用。
  • 异步编程模型:库是使用回调、事件还是Future/Promise来处理异步操作,这对于编写响应式UI至关重要。
  • 配置与状态管理:API密钥、端点URL等配置是如何在控件间传递和管理的。

6. 常见问题、排查技巧与版本兼容性处理

在实际使用和编译这类第三方源码时,会遇到各种问题。以下是一些典型问题及其解决思路。

6.1 编译与安装阶段问题

问题现象可能原因排查与解决思路
编译时提示“Unit xxx not found”1. 库路径未正确设置。
2. 依赖的其他包(如TMS Core库)未安装或路径不对。
3. 源代码包本身不完整。
1. 检查并添加所有必要的源码路径到IDE库路径。
2. 查看包文件(.dpk)的“Requires”列表,确保其中列出的所有包都已安装或能找到。
3. 对比网络上的其他资源,确认文件是否齐全。
安装时提示“Cannot load package xxx. It contains unit xxx, which is also contained in package yyy”单元冲突。同一个单元(如TMS.AI.Core)被编译进了多个不同的包中。1. 卸载所有已安装的TMS AI Studio旧版本包。
2. 清理旧的DCU/BPL文件,确保编译环境干净。
3. 尝试只编译运行时包,然后在项目中引用DCU,放弃安装设计时包。
控件安装成功,但拖到表单上提示“Class TMSAI not found”设计时包(包含控件注册信息)与运行时包(包含实际代码)版本不匹配或未正确加载。1. 关闭所有Delphi IDE实例,重新打开。
2. 检查Component -> Install Packages,确保对应的设计时包已勾选且路径正确。
3. 在系统搜索路径中,确保运行时BPL文件的目录在PATH环境变量中,或者将BPL复制到系统目录。

6.2 运行时与API调用问题

问题现象可能原因排查与解决思路
调用AI功能时,程序无响应或报网络错误。1. API密钥、BaseURL配置错误。
2. 网络代理问题。
3. 异步调用未正确处理,导致主线程阻塞。
1. 使用TMSAI控件的OnError事件捕获详细错误信息。
2. 对于本地模型(如Ollama),用浏览器访问http://localhost:11434/api/tags测试服务是否正常。
3. 检查防火墙和代理设置。在代码中为HTTP客户端显式配置代理。
4. 确保异步调用的回调函数被正确执行,避免在回调中做耗时操作。
流式输出(Streaming)不工作,必须等全部生成完才显示。1. 使用的Provider或模型不支持流式响应。
2. 代码中未正确处理流式回调事件。
1. 查阅对应AI服务的API文档,确认是否支持流式(如OpenAI的stream: true参数)。
2. 检查TMSAIChat控件是否有OnStreamingChunkReceived之类的事件,并在该事件中实时更新UI。
处理长文本时,返回“context length exceeded”错误。输入的文本(Prompt+对话历史)超过了模型的最大上下文长度(Token限制)。1. 对输入文本进行智能截断或分块总结。
2. 使用“摘要-问答”链式调用,先对长文档生成摘要,再基于摘要提问。
3. 考虑使用支持更长上下文的模型(如GPT-4 Turbo 128K)。

6.3 关于“Delphi 13.1”与版本兼容性的特别说明

项目标题中提到了“Delphi 13.1”,但Embarcadero官方发布的版本序列中,Delphi 11之后是Delphi 12 Athens。所谓的“13.1”或“Florence”很可能是发布前的内部开发代号,或者是社区/资源分享者的一种误称或未来版本占位。在处理此类资源时,版本兼容性是首要问题。

  • 向前兼容:为Delphi 12编译的包,通常无法直接在Delphi 11上安装,因为DCU/BPL格式可能不兼容,且可能使用了Delphi 12的新特性。
  • 向后兼容:为Delphi 11编译的包,在Delphi 12上可能可以安装,但可能需要重新编译。
  • 最佳实践永远尝试用源代码重新编译。打开与你当前Delphi版本最接近的.dpk文件进行编译。如果版本号不匹配(如只有D11的包,但你在用D12),直接打开D11的包,Delphi IDE通常会提示进行转换,转换后尝试编译。根据编译错误逐一调整(例如,替换过时的单元引用,修改不兼容的语法)。

一个关键的技巧是:如果包文件转换后编译困难,可以放弃安装整个包。转而创建一个新的“Package”项目,将Source目录下所有相关的.pas文件添加到这个新包中,然后编译。这样可以排除原有包项目配置的干扰。

本文还有配套的精品资源,点击获取

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

alley-oop PR 工作流:用 seed PR 实现 AI Agent 协作接力

alley-oop 这个词最早来自篮球里的“空中接力”&#xff1a;一名球员把球抛向篮筐附近&#xff0c;另一名球员在空中接住、完成得分。放在代码协作里&#xff0c;它描述的是一种非常具体的 PR 接力节奏——一个 pull request 被打开时并不是最终完成的代码&#xff0c;而是一个…

作者头像 李华
网站建设 2026/9/4 19:48:29

数字信号最佳接收三步法:从匹配滤波到误码率分析的工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 19:47:00

AI安全警示:从深度学习原理到外星智能风险与工程应对

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 19:45:25

Python密钥安全:告别硬编码,环境变量与密钥管理实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 19:43:56

STM32F103二维云台设计:从PWM控制到平滑算法的完整实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 19:42:52

用大模型API实现电商商品资料自动体检与交叉比对

一个电商运营的朋友上周找我吐槽&#xff0c;说他们团队上新品前要人工核对一堆商品资料&#xff0c;标题、卖点、详情页、参数表、资质文件&#xff0c;眼睛都快看瞎了&#xff0c;结果还是漏了好几个低级错误&#xff0c;比如详情页参数和规格表对不上、卖点文案里写的材质和…

作者头像 李华