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}`);

页面部分

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

工程新建/编辑

图片

新建

图片

编辑

工程展示

图片

展示

结果展示

图片

结果展示

 

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐