当前位置:   article > 正文

FastGPT二次开发-使用应用库进行代码Code Review

fastgpt集成到app

FastGPT 是一个基于 LLM 大语言模型的知识库问答系统,提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排,从而实现复杂的问答场景!

背景

在之前使用Gitlab CI进行AI Code Review的时候发现一些痛点,这次为了解决这些问题故在FastGPT平台上进行二次开发

现有痛点

  1. 优化提示词后需要多个项目同步修改

  2. 收集使用反馈困难

  3. 改动较多时候评论太多,影响人工评审

  4. 重试不方便

  5. Review结果不佳

为了解决这些问题从两个角度出发

  1. 将Review任务放到平台上,发起合并请求的时候使用gitlab CI触发该任务(当前二次开发部分)

  2. 维护知识库,提高Review质量

FastGPT技术栈

NextJs + TS + ChakraUI + Mongo + Postgres (Vector 插件)

将项目下载到本地后对关键路径进行分析

  • fastgpt/projects/app/src/service: 存入mongo时的存储内容,相当于表设计

  • fastgpt/projects/app/src/web/core:接口使用

  • fastgpt/projects/app/src/pages:页面路由

  • fastgpt/projects/app/src/pages/api:API路由

功能设计

工程

每个工程都可以选择对应的应用或者提示词来进行代码评审

  1. // projects/app/src/types/mongoSchema.d.ts
  2. export interface ReviewSchema {
  3.   _id: string;
  4.   appName: string;
  5.   projectId: string;
  6.   prompt?: string;
  7.   appId?: string;
  8.   createTime: Date;
  9.   lastUsedTime?: Date;
  10. }

实现增删改查

增加/修改

  1. // 增/改
  2. const { appName, prompt, projectId, appId, _id } = req.body;
  3. if (_id) {
  4.   // 传入了_id则为修改
  5.   response = await Review.updateOne({ _id }, { $set: { appName, prompt, appId, projectId } });
  6. else {
  7.   // 否则为新增
  8.   response = await Review.create({ appName, prompt, appId, projectId });
  9. }

删除

  1. const { id } = req.query;
  2. await Review.deleteOne({ _id: id });

查看

  1. const { appName, id } = req.query;
  2. let response;
  3. if (appName) {
  4.   response = await Review.find({ appName });
  5. else if (id) {
  6.   response = await Review.find({ _id: id });
  7. else {
  8.   response = await Review.find();
  9. }

任务

每次Review都是一次任务

  1. // projects/app/src/types/mongoSchema.d.ts
  2. export interface ReviewJobSchema {
  3.   _id: string;
  4.   reviewId: string// 对应ReviewSchema的_id
  5.   projectId: string// 对应ReviewSchema的projectId
  6.   mrId: string;
  7.   createTime: Date;
  8. }

查看任务

  1. const { projectId } = req.query;
  2. let response = await ReviewJob.find({ projectId }).sort({ createTime: -1 })

结果

每个任务中有多条结果记录

  1. // projects/app/src/types/mongoSchema.d.ts
  2. export interface ReviewResultSchema {
  3.   _id: string;
  4.   jobId: string// 对应ReviewJobSchema的_id
  5.   newPath?: string;
  6.   newLine?: number;
  7.   oldPath?: string;
  8.   oldLine?: number;
  9.   body: string;
  10.   ref: GitlabDiffRef;
  11.   effective?: string | null;
  12.   createTime: Date;
  13. }

查看结果

  1. const { jobId } = req.query;
  2. let response = await ReviewResult.find({ jobId }).sort({ createTime: -1 });

核心操作

功能实现采用的是【第2924期】如何在 Gitlab 中使用 ChatGPT 进行 CodeReview:https://mp.weixin.qq.com/s/Dyk1cYg63oOs13f9_gf9ug

另外需要打通使用应用库来进行CodeReview的操作

从官方文档可以看出,FastGPT使用API访问时,除域名外其他用法与直接使用Chatgpt一致,所以稍微修改一下原有的 chatgpt.ts 文件即可

这样就有两个执行文件了

  1. import run1 from '@/utils/review/chatgpt';
  2. import run2 from '@/utils/review/fastgpt';

执行任务的时候就是

  1. 根据传参查询指定工程

  2. 判断使用提示词还是应用

  3. 使用提示词则使用run1

  4. 使用的应用则使用run2

其中应用采用的是API访问,如果之前没有创建过,则新建一个,使用.lean()从数据库中拿到API Key来进行操作

  1. let { projectId, mrId, target = /\.(js|jsx|ts|tsx|java)$/} = req.query
  2. let response = await Review.find({ projectId });
  3. let prompt = response[0].prompt;
  4. let appId = response[0].appId;
  5. // 创建review任务
  6. let response1 = await ReviewJob.create({
  7.   reviewId: response[0]._id,
  8.   projectId,
  9.   mrId
  10. });
  11. let jobId = response1._id;
  12. if (appId) {
  13.   // 当有appId时,使用fastgpt
  14.   let res2;
  15.   res2 = await MongoOpenApi.findOne({ appId }).lean();
  16.   if (!res2?.apiKey) {
  17.     let res1 = await MongoUser.findOne({ username: 'root' });
  18.     let userId = res1?._id;
  19.     const nanoid = customAlphabet(
  20.       'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
  21.       Math.floor(Math.random() * 14) + 24
  22.     );
  23.     let apiKey = `${global.systemEnv?.openapiPrefix || 'fastgpt'}-${nanoid()}`;
  24.     await MongoOpenApi.create({
  25.       userId,
  26.       apiKey,
  27.       appId,
  28.       name: 'review',
  29.       limit: {
  30.         credit: -1
  31.       }
  32.     });
  33.   }
  34.   res2 = await MongoOpenApi.findOne({ appId }).lean();
  35.   if (!res2?.apiKey) throw new Error('apiKey获取失败');
  36.   run2({
  37.     gitlabConfig: {
  38.       host: 'https://gitlab.qunhequnhe.com',
  39.       token: 'xxx',
  40.       projectId,
  41.       mrIId: mrId,
  42.       target
  43.     },
  44.     fastgptConfig: {
  45.       apikey: res2.apiKey,
  46.       chatId: jobId
  47.     },
  48.     projectId,
  49.     jobId
  50.   });
  51. else {
  52.   // 当没有appId时,使用chatgpt
  53.   run1({
  54.     gitlabConfig: {
  55.       host: 'https://gitlab.qunhequnhe.com',
  56.       token: 'xxx',
  57.       projectId,
  58.       mrIId: mrId,
  59.       target
  60.     },
  61.     chatgptConfig: {
  62.       model: 'gpt-3.5-turbo-16k',
  63.       prompt,
  64.       language: 'Chinese'
  65.     },
  66.     projectId,
  67.     jobId
  68.   });
  69. }

接口

  1. import { GET, POST, DELETE, PUT } from '@/web/common/api/request';
  2. import { CreateReviewParams } from '@/types/review';
  3. /**
  4.  * 创建一个review工程任务
  5.  */
  6. export const createReviewItem = (data: CreateReviewParams) => POST<string>('/review/create', data);
  7. /**
  8.  * 获取review工程任务列表
  9.  */
  10. export const getReviewList = (appName: string | null, id: string | null) =>
  11.   GET<any>(`/review/list?appName=${appName}&id=${id}`);
  12. /**
  13.  * 删除review工程任务
  14.  */
  15. export const delReviewItem = (_id: string) => DELETE<any>(`/review/del?id=${_id}`);
  16. /**
  17.  * 开始review工程任务
  18.  * */
  19. export const startReviewItem = (projectId: string, mrId: string, target: string) =>
  20.   GET<any>(`/review/work?projectId=${projectId}&mrId=${mrId}&target=${target}`);
  21. /**
  22.  * 查询review结果
  23.  * */
  24. export const getReviewResult = (projectId: string | null, jobId: string | null) =>
  25.   GET<any>(`/review/results?projectId=${projectId}&jobId=${jobId}`);
  26. /**
  27.  * 数据概览
  28.  * */
  29. export const getReviewOverview = () => GET<any>(`/review/overview`);
  30. /**
  31.  * 修改结果是否有效
  32.  * */
  33. export const setEvaluateReviewResult = (_id: string, effective: string) =>
  34.   POST<any>(`/review/evaluateResult?_id=${_id}&effective=${effective}`);
  35. /**
  36.  * 通过jobId获取appId
  37.  * */
  38. export const getAppIdByJobId = (jobId: string) =>
  39.   GET<any>(`/review/getAppIdByJobId?jobId=${jobId}`);

页面部分

页面部分代码略,展示样式

工程新建/编辑

757a827d9a59b9bcf3273e36e41311d9.png

新建

c9512744b53115298b92d1c822084910.png

编辑
工程展示

7045dde11aebd0a45215e1271694f997.png

展示
结果展示

d9c61c677765f0ff0f9b2a94288dd549.png

结果展示
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/575605
推荐阅读
相关标签
  

闽ICP备14008679号