Delphi 12.2 开始引入了 SmartInsight 对 AI 编程模型的支持,最近简单的试用了一下,总体下自己的一点体会。先说一下结论:有比没有强,吃配置和耐心。
【补充测试】
- 使用亲戚家的 AMD 7800X3D+AMD 7800XT 16G + Windows 10 48G 平台,LMStudio 测试速度为 <40 tokens
- 传说中,LMStudio 比 Ollama 快 20%,在我个人机器上测试并不是,反而 ollama 比 LM Studio 快得多,实际应用环境,大家可以都安装测试下。
- 另外,LM Studio 中的 deepseek-coder-v2:16b 要比 ollama 的模型库中同一模型大 1GB+,这也可能是速度没有快 20% 的原因之一吧,但效率没有测试什么区别。

- 开启 AI 编程:
- 我们选择 ollama 来部署本地模型,在安装完成后,我们要选择一些合适的模型,保证我们的系统能够跑起来(以我系统 10700+32GB RAM 为基准),经过测试:
- deepseek-coder-v2:16b 速度 17.68 tokens/s,在 7950X+64G DDR5 6200+1050 ti 跑出了接近 40tokens/s 的速度(Deepin v23+ollama 0.6.2)
- qwen2.5-coder:7b 速度 7.26 tokens/s
- codegemma:7b 速度 6.08 tokens/s
- starcoder2:7b 速度 13.70 tokens/s,但我问什么他直接原文回复我是什么鬼?
- stable:3b 速度 14.94 tokens/s,不过 3b 参数太少
- 所以综上,deepseek-coder-v2:16b 在我目前的机器上应该是比较好的一个选择
- 我们选择 ollama 来部署本地模型,在安装完成后,我们要选择一些合适的模型,保证我们的系统能够跑起来(以我系统 10700+32GB RAM 为基准),经过测试:
- 实际体验:
- 响应速度: 感觉没有采用SSE模式,所以需要等待全部返回才能得到结果,会给人感觉比较慢。
- 功能可用性:不要指望 CodeSight AI 的实时提示及分析,这个功能对算力的要求太高。目前可以主要可能完成:
– 代码的阅读理解:让 AI 解释代码的执行流程,方便读别人的代码
– 查找问题及解决方案:让 AI 检查你的函数是否有问题,做到 AI 辅助审查代码
– 为代码添加注释:可以省下你的很大一部分写注释的精力
– 优化代码:可以用来帮你调整优化代码
– 其它功能:可以用,看需要和耐心,简单的代码等他出来,你可能早写完了。 - 结果反馈:默认情况下,由于发起请求都是英文,所以回答都是英文。如果我们要让 AI 回复中文,需要在内容中包含“中文”这个关键词即可,比如下面就可以让回复中文,不过最安全是的写”使用中文回复”一类的字样:
//中文
procedure Test();
var
p,pd: PInteger;
begin
GetMem(p, 100);
try
pd:=p;
for var I := 0 to 25 do
begin
pd^ := 0;
Inc(pd);
end;
finally
FreeMem(p);
end;
end;
上面的代码选中,然后选择 SmartCodeInsight->Explain the Code,结果如下:
(************* Explanation
***************
这段代码是一个Delphi或Pascal语言的程序,用于分配内存并初始化这块内存。下面是对代码的详细解释:
```delphi
//中文
procedure
Test();
var
p, pd: PInteger;
begin
GetMem(p, 100); //
分配一块大小为100字节的内存,返回一个指向该内存的指针,赋值给变量p
try
pd := p; //
将指针p赋值给pd,此时pd也指向同一块内存
for var I := 0 to 25 do // 使用for循环从0到25进行迭代
begin
pd^ := 0; // 将当前pd所指向的内存单元设置为0
Inc(pd); // 将pd指向下一个内存单元
end;
finally
FreeMem(p); // 释放分配的内存,无论之前是否发生异常都会执行这一步
end;
end;
```
### 代码解释:
1. **分配内存**:
```delphi
GetMem(p, 100);
```
这行代码调用`GetMem`函数,分配一块大小为100字节的内存,并返回一个指向这块内存的指针。这个指针被赋值给变量`p`。
2.
**初始化内存**:
```delphi
pd := p;
for var I := 0 to 25 do
begin
pd^ := 0;
Inc(pd);
end;
```
这里,首先将指针`p`赋值给`pd`,使得它们指向同一块内存。然后使用一个`for`循环从0到25进行迭代,每次迭代都将当前`pd`所指向的内存单元设置为0,并将`pd`指向下一个内存单元。
3.
**释放内存**:
```delphi
finally
FreeMem(p);
end;
```
无论在循环中是否发生异常,最后都会执行`FreeMem(p)`来释放之前分配的内存。
###
总结:
这段代码的主要功能是分配一块大小为100字节的内存,然后通过一个循环将这块内存的前26个整数(每个4字节)初始化为0。最后,无论循环过程中是否发生异常,都会确保释放分配的内存。
*)
如果我们不选中中文这行注释, 它返回的结果是:
(************* Explanation ***************
The code you've provided is a
Pascal procedure named `Test()`. This procedure uses dynamic memory allocation
and manipulation in Pascal. Here's a step-by-step breakdown of what the code
does:
1. **Variable Declarations**:
```pascal
var p, pd: PInteger;
```
- `p` is declared as a pointer to an integer.
- `pd` is also
declared as a pointer to an integer, but it will be used to iterate over the
memory block allocated for `p`.
2. **Memory Allocation**:
```pascal
GetMem(p, 100);
```
- This line allocates a block of memory with a size
of 100 bytes and assigns the pointer to this block to `p`. The allocated memory
is uninitialized and can be used to store integers.
3. **Memory
Initialization**:
```pascal
try
pd := p;
for var I := 0 to
25 do
begin
pd^ := 0;
Inc(pd);
end;
finally
FreeMem(p);
end;
```
- The `try` block is used to ensure that the
allocated memory is properly freed in case an exception occurs during its use.
- `pd := p;` initializes `pd` to point to the same memory location as `p`.
-
The `for` loop iterates 26 times (from 0 to 25), setting each integer value in
the allocated block to 0:
```pascal
for var I := 0 to 25 do
begin
pd^ := 0;
Inc(pd);
end;
```
- `pd^ :=
0;` sets the current integer value at the address pointed to by `pd` to 0.
- `Inc(pd);` increments the pointer `pd` to point to the next integer in the
memory block.
- The finally clause ensures that the allocated memory is
freed using `FreeMem(p);` even if an exception occurs during the execution of
the procedure.
4. **Memory Deallocation**:
```pascal
FreeMem(p);
```
- This line frees the dynamically allocated memory block pointed to by
`p`.
### Summary
The `Test()` procedure allocates a block of memory for 100
integers, initializes the first 26 integers to zero, and then deallocates the
memory. The use of `try...finally` ensures that the memory is always freed, even
if an error occurs during the initialization process.
*)
下面是接入 DeepSeek API 做的代码完成测试的返回结果,先中前面的注释,然后右键选择 SmartInsight -> Complete the Code:
// 当前界面上 Memo1 存的是一个 JSON 字符串,帮我完成解析并获取其中名为 url 的成员的值,然后将其赋给 Edit1.Text
(************* Complete Code ***************
要完成这个任务,你可以使用 Delphi 的
`System.JSON` 单元来解析 JSON 字符串。以下是一个完整的代码示例,展示了如何从 `Memo1` 中获取 JSON 字符串,解析它,并提取名为
`url` 的成员的值,然后将其赋值给 `Edit1.Text`。
```delphi
uses
System.JSON;
procedure TForm1.Button1Click(Sender: TObject);
var
JSONString: string;
JSONValue: TJSONValue;
JSONObject: TJSONObject;
URLValue: string;
begin
// 获取 Memo1 中的 JSON 字符串
JSONString :=
Memo1.Text;
try
// 解析 JSON 字符串
JSONValue :=
TJSONObject.ParseJSONValue(JSONString);
if JSONValue is TJSONObject then
begin
JSONObject := JSONValue as TJSONObject;
// 获取名为 "url"
的成员的值
if JSONObject.TryGetValue<string>('url', URLValue) then
begin
// 将获取到的值赋给 Edit1.Text
Edit1.Text := URLValue;
end
else
begin
ShowMessage('JSON 中未找到 "url" 成员');
end;
end
else
begin
ShowMessage('JSON 字符串格式不正确');
end;
finally
// 释放 JSONValue
JSONValue.Free;
end;
end;
```
### 代码说明:
1. **获取 JSON 字符串**:从 `Memo1` 中获取 JSON 字符串。
2.
**解析 JSON 字符串**:使用 `TJSONObject.ParseJSONValue` 方法解析 JSON 字符串。
3. **检查 JSON
类型**:确保解析后的 JSON 是一个对象(`TJSONObject`)。
4. **获取 `url` 成员的值**:使用 `TryGetValue`
方法尝试获取名为 `url` 的成员的值。
5. **赋值给 `Edit1.Text`**:如果成功获取到 `url` 的值,将其赋值给
`Edit1.Text`。
6. **错误处理**:如果 JSON 格式不正确或未找到 `url` 成员,显示相应的错误消息。
7.
**释放资源**:最后释放 `JSONValue` 对象,避免内存泄漏。
### 注意事项:
- 确保 `System.JSON` 单元已经被添加到
`uses` 子句中。
- 如果 JSON 字符串格式不正确或 `url` 成员不存在,代码会显示相应的错误消息。
- 这个代码假设 `Button1`
是一个按钮,点击按钮时执行解析操作。你可以根据需要调整触发事件。
希望这个代码对你有帮助!
*)