谁说 AI 编程工具缺乏记忆和联想能力?简单琐碎的需求完全可以交给它

人工智能
亚马逊云科技
Amazon CodeWhisperer
生成式人工智能
0
0
> **[Amazon CodeWhisperer](https://aws.amazon.com/cn/codewhisperer/?trk=cndc-detail)** 是一款 AI 编码配套应用程序,可在 IDE 中生成整行代码和完整的函数代码建议,以帮助您更快地完成更多工作。在本系列文章中,我们将为您详细介绍 [Amazon CodeWhisperer](https://aws.amazon.com/cn/codewhisperer/?trk=cndc-detail) 的相关信息,敬请关注! 2023年可以说是生成式 AI 正式破圈的一年。无数的工具、产品横空出世,包括面向企业的大语言模型,以及帮助个人的 AI 工具。其中,在 AI 编程助手领域,也涌现了很多不错的产品,潜移默化中改变了程序员们生产和解决问题的方式。以前,大家往往依靠搜索引擎,找到对应官网或在知名论坛寻找答案;而如今,我们仅依靠 AI 编程助手,就能解决很多问题。 亚马逊云科技就推出了一款 AI 编程助手—— **[Amazon CodeWhisperer](https://aws.amazon.com/cn/codewhisperer/?trk=cndc-detail)**,能够使用您的 AI 编码配套应用程序更快、更安全地构建应用程序。亚马逊云科技在 AI 领域有足够多的积累,在面向开发者方面亦有足够多的经验、产品用户体验来反馈用户感受,并不断迭代着相关产品。同时,借助亚马逊云的强大优势和力量,能够将 AI 和云打通,这在当前云原生时代是必不可少的能力。 ### **目标及前期准备** 先给大家介绍下今天我们希望实现的目标:基于 **Spring Boot** 框架,简单实现用户登陆。我们使用的是 **IntelliJ** 开发工具,选用 Maven 进行依赖管理。用到的依赖如下: * Web * JPA * H2 我们首先尝试安装 CodeWhisperer 插件,在 Plugins 中搜索 Amazon Toolkit 下载即可。 ![image.png](https://dev-media.amazoncloud.cn/f7863f16c6af4e3d81e9cc5a813904e9_image.png "image.png") 下载完成后绑定自己的亚马逊账号即可开始使用,默认开启自动建议。 项目结构如图所示: ![image.png](https://dev-media.amazoncloud.cn/300b150ceb6e44da9aed9747eb0ac029_image.png "image.png") pom.xml 文件如下: ``` <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.0</version> <relativePath/> <!-- lookup parent from repository -->   </parent> <groupId>com.example</groupId>   <artifactId>demo</artifactId>   <version>0.0.1-SNAPSHOT</version>   <name>demo</name> <description>demo</description> <properties>     <java.version>17</java.version> </properties> <dependencies>     <dependency>       <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>    <dependency>       <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency>       <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>     </dependency>    <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>     </dependency>   </dependencies>  <build>     <plugins>       <plugin>         <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin>     </plugins> </build> </project> ``` <!--StartFragment--> ### **开始** ##### **健康检查** 我们先实现一个最简单的 **Controller**,请求 **/ping** 返回 **pong** 即可。 ``` package com.example.demo.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class PingController {    @RequestMapping("/ping") public @ResponseBody String greeting() {         return "pong";     } } ``` 测试用例是检验代码正确性必不可少的一环,我们来写个简单的测试用例。这时 CodeWhisperer 已经开始展示它的实力了,只是写了一行 @Test 注解,它将我们想要做的测试代码完整提示出来: ![image.png](https://dev-media.amazoncloud.cn/43d5e48c0df24762a1cb6b072c0122f5_image.png "image.png") 下面是完整的测试代码: ``` package com.example.demo; import com.example.demo.controller.PingController; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @AutoConfigureMockMvc @WebMvcTest(PingController.class) public class TestWebApplication {     @Autowired     private MockMvc mockMvc;    @Test     public void shouldReturnDefaultMessage() throws Exception { this.mockMvc.perform(get("/ping")).andDo(print()).andExpect(status().isOk()) .andExpect(content().string("pong"));     } } ``` 运行一下测试用例,很顺利地通过了: ![image.png](https://dev-media.amazoncloud.cn/c766b01f23784e0094fb8a39611749d6_image.png "image.png") ##### **用户类设计** 我们来定一个 **User** 模型,发现它在 Table To Class 的实现中具备一定的表设计能力,以及字段关联联想、约束设计能力。 ![image.png](https://dev-media.amazoncloud.cn/a735ea466c28477f8698b02af30c6a0e_image.png "image.png") ![image.png](https://dev-media.amazoncloud.cn/6d5ced812c124b25bb545225683626f1_image.png "image.png") 能推测我们想要的表字段,索引约束建议。这对于新手来说是莫大的帮助。想象有一位“功力深厚”的同伴在旁指点你设计表结构,那么表结构的设计就能相对合理一些。 ``` package com.example.demo.model; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import org.springframework.stereotype.Indexed; @Entity @Getter @Setter @AllArgsConstructor @NoArgsConstructor @Table(name = "game_users") public class User {     @Id     private Long id;     @Column(unique = true, nullable = false)     private String username;     @Column(nullable = false, length = 64)     private String password;     @Column(unique = true, nullable = false)     private String email;} ``` ##### **DAO 层实现** 根据官网的 GIF 图展示,可以通过注释进行代码推断,DAO 层的实现就交给它: ![image.png](https://dev-media.amazoncloud.cn/7748140a98cc441eb74bdc481f640a7d_image.png "image.png") 根据我们上面想要根据邮箱查询用户的注释,它已经给出了相应的提示。让我们再考考它,注释中进行多个方法的描述: ![image.png](https://dev-media.amazoncloud.cn/a9d9b8f924bd4271b86b6d03e9bd220c_image.png "image.png") 也很顺利地实现了! ``` package com.example.demo.dao; import com.example.demo.model.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.Optional; @Repository public interface UserDao extends JpaRepository<User, Long> {     // function to implement find user by email     Optional<User> findByEmail(String email);    Optional<User> findByUsername(String username);    // two function to implement find user by id or email Optional<User> findById(Long id);     Optional<User> findByEmailIgnoreCase(String email);    // function to implement check user is existed     Boolean existsByEmail(String email); } ``` 综上,**CRUD** 的 **DAO** 层实现可以交给 CodeWhisperer 来完成。我们希望能够预先插入一些数据便于测试,琐碎的日志测试对它来说轻轻松松。 ![image.png](https://dev-media.amazoncloud.cn/ba99f978e51f4ef19b7593ff6e6ed9c9_image.png "image.png") ``` package com.example.demo; import com.example.demo.dao.UserDao; import com.example.demo.model.User; import org.slf4j.Logger; import org.springframework.boot.CommandLineRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration class LoadDatabase {     public static final Logger log = org.slf4j.LoggerFactory.getLogger(LoadDatabase.class);    // this is Bean is loaded once in the application context     // it is used to load the data into the database     @Bean     public CommandLineRunner initDatabase(UserDao dao) {         return args -> {             log.info("Preloading " + dao.save(new User(1L, "test1", "111111", "abc@gmail.com")));             log.info("Preloading " + dao.save(new User(2L, "test2", "222222", "123@gmail.com")));         };     } } ``` ##### **Service 层实现** 轮到 **Service** 层了,在这里我们简单的根据用户名查询用户,返回对应的数据即可。当我们方法签名写一半时,它给的建议是停下继续敲击的手指,因为基本符合预期,而且具备一定的记忆联想能力。在 **DAO** 层定义的 **Optional\<User>**,这里也能找到对应的方法进行处理。 ![image.png](https://dev-media.amazoncloud.cn/c2c4f336c6a242188083d377d5a99719_image.png "image.png") ``` package com.example.demo.service; import com.example.demo.dao.UserDao; import com.example.demo.model.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Optional; @Service public class UserDetailServiceImpl {     private final UserDao userdao;    @Autowired     public UserDetailServiceImpl(UserDao userdao) {         this.userdao = userdao;     }    public User getUserByUsername(String username) throws Exception { Optional<User> user = userdao.findByUsername(username); if (user.isPresent()) {             return user.get();         } else {             throw new Exception("User not found");         }     } } ``` ##### **Controller 层实现** 最后,我们来实现最外层入口,简单的进行相关业务校验:用户名是否为空、密码是否正确。在这里用于演示。 ![image.png](https://dev-media.amazoncloud.cn/abcc964c2ba342128af6268889b2bc85_image.png "image.png") ![image.png](https://dev-media.amazoncloud.cn/164354a1029247949758e73b6dd0a28b_image.png "image.png") 用户不存在相关处理,密码正确性验证,基本符合我们的要求。 ``` package com.example.demo.controller; import com.example.demo.model.User; import com.example.demo.service.UserDetailServiceImpl; import org.apache.coyote.Response; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/auth") public class UserController {     private final UserDetailServiceImpl userDetailService;    @Autowired     public UserController(UserDetailServiceImpl userDetailService) { this.userDetailService = userDetailService; }    @PostMapping("/login")     public ResponseEntity<?> login(@RequestBody User user) {         try {             if (user.getUsername().isEmpty()) {                 return ResponseEntity.badRequest().body("user name is empty");             }            User res;             res = userDetailService.getUserByUsername(user.getUsername());             if (res == null) {                 return ResponseEntity.badRequest().body("user not  found");             }            if (res.getPassword().equals(user.getPassword())) { return ResponseEntity.ok(res);             }             return new ResponseEntity<>("user password invalid", HttpStatus.BAD_REQUEST);       } catch (Exception e) {             return ResponseEntity.notFound().build();         }     } } ``` 最后我们来测试一下,格式错误和用户密码错误的情况。 ![image.png](https://dev-media.amazoncloud.cn/20436413a9e64a98ad712c7786bdd1b7_image.png "image.png") ![image.png](https://dev-media.amazoncloud.cn/0cc0282eebd64de28eec2dea32d4175c_image.png "image.png") ![image.png](https://dev-media.amazoncloud.cn/45b2f6b0432e4757b513223303479219_image.png "image.png") <!--StartFragment--> 与预期一致。 ### **总结** CodeWhisperer 就我们今天的使用而言,还是非常智能和便捷的。作为一款具备记忆和联想能力的 AI 编程工具,今天 CodeWhisperer 展示的记忆联想效果很不错,并且具备一定的表结构设计能力,一些简单的测试用例完成度也不错。未来一些简单琐碎的需求、测试用例也可以交给它了。针对一些更复杂的场景,随着模型的数据量级和质量不断优化,相信我们都能够陆续解决! ![640.gif](https://dev-media.amazoncloud.cn/befd30d01bcf4d78bd9f79a628a0ab16_640.gif "640.gif")
0
目录
关闭