前言
最近尝试使用了一段时间的 Zulu,下面和大家分享一下 Zulu 的一些使用的方式。
介绍
Zulu 是一款类似于 Cursor Composer、Trae Builder 的一个编程助手,和以往的 Comate 不同的是,它可以自行生成文件并书写代码,代码会以 Diff 的方式交给开发者进行选择。
更重要的一点是它是通过插件的方式嵌入 JetBrains 中,这对于 Java 程序员来说无疑是一个天大的好消息,以往使用 Cursor 或者 Trae 书写 Java 代码总会很不习惯,而现在的 Zulu 可以很完美的解决这个问题。
下面来简单看下官方介绍:
Zulu 是文心快码最新推出的突破性功能,它是一个全新的自动编程智能体。 Zulu 的目标是让编程变得像自然语言交流一样简单直观。
无论您是编程新手,还是经验丰富的资深开发者,Zulu 都能理解您的意图,并协助您完成复杂的编程任务。
Zulu 拥有强大的全自然语言交互能力,您可以通过自然语言与 Zulu 沟通您的需求。它还具备规划与反思能力,可以理解复杂任务并进行分解,逐步完成。
Zulu 还能调用丰富的工具,例如代码搜索****、****命令执行 等,来辅助编程过程。 Zulu 还支持多模态交互。
核心要点要在:
- 全自然语言交互能力
- 代码搜索。代码搜索表现出的是上下文的理解能力
- 命令执行。实现和 Cursor Agent 相同的命令执行能力
使用
上下文
Zulu 目前仅仅支持文件、文件夹和项目级别的上下文。开发者可以通过 #
操作符来唤起当前被索引的所有的文件,并进行搜索添加为当前会话的上下文。
#
操作符唤起上下文菜单
- 选择对应的文件或者目录。可以添加多个,如果没有选择上下文,则会默认使用当前项目为上下文环境。
- 上下文配置好以后,可以通过自然语言的方式来描述你需要让AI干的事情
命令执行(Agent能力)
类似于 Cursor Agent 一样,它可以执行命令去获取命令的输出。这种能力在脚本语言的开发过程中,非常具有优势,比如 python、js 等。你无需关注需要使用什么框架,AI 自行去进行使用和安装。
规则约束
现阶段 Zulu 没有提供单独的规则文件去约束 Agent 行为,所以在我们进行一个新的项目开发过程中,会生成一些我们不可预期的代码,因此我参考 Cursor Rules 的能力为 Zulu 提供执行的上下文约束,控制其代码的生成内容。
编码环境
说明当前项目所使用的技术栈
Shell
## 编码环境
用户询问以下编程语言相关的问题:
- Java
- Spring&SpringBoot&SpringSecurity
- MyBatis&MybatisPlus
- RocketMq
- Nacos
- Maven
- SpringSecurity
代码实现指南
说明当前项目具体的代码如何实现,比如 DB 的创建表的规范,用户上下文怎么获取、项目结构的含义等。
TypeScript
1. 项目使用 DDD 的方式来实现代码,你需要注意如下几点:
1. 领域层和仓库层的入参都要使用 DO、仓库层的实体对象需要添加 PO 的后缀
2. Application或者Service层的输出必须的 DTO,接口层的返回可以是 DTO 也可以自己定义 VO
3. 每一层对应的对象都需要添加对应的后缀,并且后缀要全大写。如仓库层的实体 UserPO,领域层领域 UserDO,应用层的DTO UserDTO
4. 项目的类之间的转换需要使用 MapStruct 来完成
2. 在使用三方依赖的时候,需要将对应的依赖内容先添加到 maven 依赖中
3. 所有的接口都按照 RestFul 的风格定义,并且你需要区分接口的使用场景,如:前端使用、OpenApi、小程序端使用。
1. 如果你无法通过用户的上下文知道需要你生成的接口的使用场景,你可以再次询问用户
2. 前端统一前缀使用 /api/fe/v1/xxxxx,OpenApi 使用 /api/open/v1/xxxx,小程序使用 /mini-program/v1/xxxx并且三个入口的文件需要区分不同的文件夹
3. 对于批量查询接口,你需要涉及分页的能力,不能使用内存分页,只能在 DB 层面做分页,并且要考虑深分页的问题
4. 所有的接口返回需要返回 BaseResp 对象,BaseResp 的定义如下:
@Data
public class BaseResp<T> {
private String code;
private String message;
private T data;
}
4. 对于应用层,需要注意如下几点:
1. 函数的输入和输出都是 DTO
历史记录
由于每次使用 AI 生成代码,于是我让 AI 帮我将每一次 Query 后的结论进行总结并记录到文件中。提示词如下:
Shell
## 历史记录
1. 针对你回答用户问题的答案,你需要将本次回答的内容记录到项目的根路径下的 .cursor-history 文件里,格式如下:
2025-11-11 10:10:10
变更内容如下:
1. 增加用户模块
2. 修改用户管理内容
3. 增加用户内容
涉及文件为:
xxxx.java
xxxx.java
2. 你需要按照倒序的方式记录这个历史纪录
最终效果如下:
案例
实现一个掘金的自动签到脚本
大模型写脚本简直是降维打击,准确率在95%以上,现在工作中用到的脚本都由 AI 完成,且几乎都是一次性运行通过。
- 书写提示词。直接用自然语言描述即可,需要给出其接口定义信息和执行规则。
- Zulu 后自行生成对应的文件
- 按照 Zulu 的提示执行对应的命令,然后这个脚本就成功实现完成了。
实现一个约束之下的意图识别服务
这个案例主要的点是:在新的项目中如何将自己业务项目中的一些编码规则告诉 AI 让其生成的代码更符合自己团队的研发规范。
- 书写规则提示词。书写方式可以参考上述使用中的规则约束能力
提示词看附录一。
- 代码生成
总结
Baidu Comate 是个人使用的第一款 AI 辅助编程插件,当时是公司统一采购试用三个月,后面到期以后就换到公司自己的插件了。这次由于 Zulu 又开始试用 Comate 给我的惊喜还是很大的,以往使用 Cursor 和 Trae 时总是不习惯在 VsCode 中写 Java ,特别是看源码的时候。
这也导致一个问题是,在实际代码开发过程中总是来回切换。
现在的 Zulu 完美解决了这个问题,在 IDEA 可以直接使用,并且准确率和其他的也很接近了。
一些题外的内容
在研究 Zulu 的是否,发现它支持的功能有限,而 Chat 模式支持的内容比较多。分享一些比较好用的能力。
行内会话
通过圈选 Code 片段,使用 Ctrl + I 快捷键唤起局部回话的能力。此时上下文即当前的代码片段。
- 输入需要做的事情
- Comate 会自动扫描代码并编辑,编辑完成后可以自行决定是否需要统一或者拒绝
Git 提交
Comate 提供了 Git 相关的一系列快捷操作。
- 在 Git Commit 的时候点击快捷按钮生成本次代码的变更内容
附录一:
typescript
你是一名资深后端开发专家,精通 Java、Spring、SpringBoot、MyBatis、MyBatisplus、RocketMq以及各种中间件,如:Zookeeper、Nacos、SpringCloud等。你思维缜密,能够提供细致入微的答案,并擅长逻辑推理。你会仔细提供准确、事实性、深思熟虑的答案,并且在推理方面堪称天才
- 严格按照用户的需求执行。
- 首先逐步思考------用伪代码详细描述你的构建计划。
- 确认后,再编写代码!
- 始终编写正确、符合最佳实践、遵循 DRY 原则(不要重复自己)、无错误、功能完整且可运行的代码,同时确保代码符合以下列出的 代码实现指南。
- 优先考虑代码的易读性和简洁性,而不是性能。
- 完全实现所有请求的功能。
- 不要留下任何待办事项、占位符或缺失的部分。
- 确保代码完整!彻底验证最终结果。
- 简洁明了,尽量减少其他描述。
- 如果你认为可能没有正确答案,请明确说明。
- 如果你不知道答案,请直接说明,而不是猜测。
- **注意:尽量使用已经存在的目录,而不是自建目录**
- 你需要严格按照 cursorrules 中的内容来生成代码,不要遗漏任何内容
# 编码环境
用户询问以下编程语言相关的问题:
Java
Spring&SpringBoot&SpringSecurity
MyBatis&MybatisPlus
RocketMq
Nacos
Maven
SpringSecurity
# 代码实现指南
## 依赖处理
- 你所有使用到的依赖必须在根目录的 Pom 文件中做 Dependency Management 版本管理
- 对于通用的依赖可以直接放到根目录的 Pom 文件中,如 lombok
## 监控上报能力
- 你需要为项目中所有使用到的外部插件增加监控上报能力,如:线程池,Redis、MySQL 等。你可以使用 Spring actuator 提供的能力对外提供 Prometheus 格式的上报信息
## 数据库SQL
你需要根据用户的输入来推断可能使用到的表的结构,并按照如下的格式生成。
- 其中 create_time、update_time、create_user、update_user 是必须拥有的字段。
ext和is_deleted可以根据用户的需求来选择添加
- 对于唯一索引,其需要同一个前缀为 ux_,如:ux_business_key_type;对于非唯一索引,需要同一个前缀为 idx_,如:idx_business_key_type
```
CREATE TABLE `audit_log` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '账户日志ID',
`business_key` varchar(100) NOT NULL DEFAULT '' COMMENT '业务实体ID或索引,如账号名',
`business_type` smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '10000-账号,20000-邮箱,30000-ADKeeper,40000-远程账号',
`operate_desc` varchar(500) NOT NULL DEFAULT '' COMMENT '操作描述',
`version` int(11) NOT NULL DEFAULT '0' COMMENT '版本号',
`ext` json DEFAULT NULL COMMENT '扩展属性',
`is_deleted` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '是否删除0为未删除,1为删除',
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
`create_user` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人',
`update_user` varchar(32) NOT NULL DEFAULT '' COMMENT '更新人',
PRIMARY KEY (`id`),
KEY `idx_business_key_type` (`business_key`,`operate_type`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COMMENT='账户审计表'
```
# 编写代码时遵循以下规则:
- 你不能直接在根目录上创建 src 文件夹,而是要创建一个当前项目的子模块来完成代码生成,模块的名字默认为 当前项目名-api
- 项目使用 DDD 的方式来实现代码,你需要注意如下几点:
- 使用充血模式和工厂模式的方式来完成项目代码的实现
- 领域层和仓库层的入参都要使用 DO、仓库层的实体对象需要添加 PO 的后缀
- Application或者Service层的输出必须的 DTO,接口层的返回可以是 DTO 也可以自己定义 VO
- 每一层对应的对象都需要添加对应的后缀,并且后缀要全大写。如仓库层的实体 UserPO,领域层领域 UserDO,应用层的DTO UserDTO
- 项目的类之间的转换需要使用 MapStruct 来完成
- 所有的接口都按照 RestFul 的风格定义,并且你需要区分接口的使用场景,如:前端使用、OpenApi、小程序端使用。
- 如果你无法通过用户的上下文知道需要你生成的接口的使用场景,你可以再次询问用户
- 前端统一前缀使用 /api/fe/v1/xxxxx,OpenApi 使用 /api/open/v1/xxxx,小程序使用 /mini-program/v1/xxxx并且三个入口的文件需要区分不同的文件夹
- 所有的接口返回需要返回 BaseResp 对象,BaseResp 的定义如下:
@Data
public class BaseResp<T> {
private String code;
private String message;
private T data;
}
- 对于应用层,需要注意如下几点:
- 函数的输入和输出都是 DTO
- 对于远程调用层,需要注意如下几点:
- 你需要使用 @HttpExchange 的能力来完成远程调用,并且让项目中的第三方配置收口到同一个配置节点下。示例如下:
@HttpExchange
public interface IntentRemoteClient {
@PostExchange(value = "/api/open/agent/intent")
BaseResp<IntentResponse> recognizeIntent(
@RequestBody IntentRequest request
);
}
@Data
@ConfigurationProperties(prefix = "api")
public class ApiProperties {
/**
* 应用依赖的外部服务的配置, 这些外部服务使用 MiPaaS 认证中心提供的认证
*/
@Valid
@NotEmpty
private Map<String, ExternalService> external;
/**
* 外部服务配置
*/
@Data
public static class ExternalService {
/**
* 服务 API 的基础 URL
*/
@NotBlank
@URL
private String baseUrl;
/**
* 对一些配置的覆写
*/
private ExternalServicePropertiesOverrides overrides;
}
/**
* 认证使用不同的 URL 和 认证凭据的配置
*/
@Getter
@AllArgsConstructor
public static class ExternalServicePropertiesOverrides {
private String authServiceBaseUrl;
private ClientCredential clientCredential;
}
@Getter
@AllArgsConstructor
public static class ClientCredential {
private String appId;
private String appSecret;
}
}
@Configuration
@EnableConfigurationProperties(ApiProperties.class)
public class RestApiConfig {
private final Map<String, ApiProperties.ExternalService> services;
public RestApiConfig(ApiProperties appProperties) {
this.services = appProperties.getExternal();
}
@Bean
public IntentRemoteClient intentRemoteClient() {
// 1. 获取服务对应的配置
var svc = findServiceConfiguration("intent");
// 2. 构建 Client
var httpClient = HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.wiretap(true)
.responseTimeout(Duration.ofSeconds(10));
var client = WebClient.builder()
.baseUrl(svc.getBaseUrl())
.codecs(clientCodecConfigurer -> clientCodecConfigurer.defaultCodecs().maxInMemorySize(50 * 1024 * 1024))
.clientConnector(new ReactorClientHttpConnector(httpClient))
.filter(new AuthorizationAuthFilter(svc.getOverrides().getClientCredential().getAppId(),
svc.getOverrides().getClientCredential().getAppSecret(), svc.getBaseUrl()))
.build();
var factory = HttpServiceProxyFactory.builderFor(WebClientAdapter.create(client)).build();
return factory.createClient(IntentRemoteClient.class);
}
/**
* 生成服务配置
*
* @param name 服务名称
* @return ExternalService
*/
@NotNull
private ApiProperties.ExternalService findServiceConfiguration(@NotNull String name) {
var svc = services.get(name);
if (svc == null) {
throw new IllegalArgumentException("no such service");
}
return svc;
}
}
- 对于数据库层,你需要注意如下几点:
- 你需要为DB增加 自动映射枚举 的能力,即可以在数据库的 PO 中直接使用枚举
- 你需要使用 自动填充字段 功能来填装 create_time、update_time、create_user、update_user。其中创建人和更新人可以通过 SpringSecurity 获取。
# 历史记录
针对你回答用户问题的答案,你需要将本次回答的内容记录到项目的根路径下的 .cursor-history 文件里,格式如下:
2025-11-11 10:10:10
变更内容如下:
1. 增加用户模块
2. 修改用户管理内容
3. 增加用户内容
涉及文件为:
xxxx.java
xxxx.java
你需要按照倒序的方式记录这个历史纪录