From 3444e2015b126e7240325250129dc0c1d361c8d0 Mon Sep 17 00:00:00 2001 From: Adrian Machado Date: Fri, 22 Sep 2023 16:11:59 -0700 Subject: [PATCH 1/7] AI summary --- apps/web/src/app/report/[id]/page.tsx | 8 ++++++- .../src/app/report/[id]/report-summary.tsx | 22 +++++++++++++++++++ .../components/DetailedScoreSection/index.tsx | 2 +- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 apps/web/src/app/report/[id]/report-summary.tsx diff --git a/apps/web/src/app/report/[id]/page.tsx b/apps/web/src/app/report/[id]/page.tsx index 9576466..085386d 100644 --- a/apps/web/src/app/report/[id]/page.tsx +++ b/apps/web/src/app/report/[id]/page.tsx @@ -6,6 +6,7 @@ import ShareButton from "@/components/ShareButton"; import DynamicBackground from "@/components/DynamicBackground"; import { FullReport } from "./full-report"; import { SimpleReport, getSimpleReport } from "./simple-report-request"; +import ReportSummary from "./report-summary"; const HeroScore = async ({ simpleReport }: { simpleReport: SimpleReport }) => { return ( @@ -37,7 +38,12 @@ const ReportPage = async ({ params }: { params: { id: string } }) => { return ( <> - {simpleReport.summary ?
{simpleReport.summary}
: null} + {simpleReport.summary ? ( + + ) : null} ); diff --git a/apps/web/src/app/report/[id]/report-summary.tsx b/apps/web/src/app/report/[id]/report-summary.tsx new file mode 100644 index 0000000..e75f70a --- /dev/null +++ b/apps/web/src/app/report/[id]/report-summary.tsx @@ -0,0 +1,22 @@ +import getScoreTextColor from "@/utils/get-score-test-color"; + +type ReportSummaryProps = { + summary: string; + score: number; +}; + +const ReportSummary = ({ summary, score }: ReportSummaryProps) => { + const scoreTextColor = getScoreTextColor(score); + return ( +
+

+ Summary (AI Generated) +

+

{summary}

+
+ ); +}; + +export default ReportSummary; diff --git a/apps/web/src/components/DetailedScoreSection/index.tsx b/apps/web/src/components/DetailedScoreSection/index.tsx index 9a696b6..2e46687 100644 --- a/apps/web/src/components/DetailedScoreSection/index.tsx +++ b/apps/web/src/components/DetailedScoreSection/index.tsx @@ -96,7 +96,7 @@ const DetailedScoreSection = ({ Severity - Suggestion + Issue From 4dcf1873bd2ecff0ab0361ede18840e21dc006ec Mon Sep 17 00:00:00 2001 From: Adrian Machado Date: Fri, 22 Sep 2023 16:33:17 -0700 Subject: [PATCH 2/7] Change alignment of text --- apps/web/src/app/report/[id]/report-summary.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/app/report/[id]/report-summary.tsx b/apps/web/src/app/report/[id]/report-summary.tsx index e75f70a..e3ba273 100644 --- a/apps/web/src/app/report/[id]/report-summary.tsx +++ b/apps/web/src/app/report/[id]/report-summary.tsx @@ -8,7 +8,7 @@ type ReportSummaryProps = { const ReportSummary = ({ summary, score }: ReportSummaryProps) => { const scoreTextColor = getScoreTextColor(score); return ( -
+

From 0078fdf869f488b2e1da0608755028e9ee36b748 Mon Sep 17 00:00:00 2001 From: Adrian Machado Date: Fri, 22 Sep 2023 16:38:02 -0700 Subject: [PATCH 3/7] Fix padding --- apps/web/src/app/report/[id]/report-summary.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/app/report/[id]/report-summary.tsx b/apps/web/src/app/report/[id]/report-summary.tsx index e3ba273..9b800ff 100644 --- a/apps/web/src/app/report/[id]/report-summary.tsx +++ b/apps/web/src/app/report/[id]/report-summary.tsx @@ -8,7 +8,7 @@ type ReportSummaryProps = { const ReportSummary = ({ summary, score }: ReportSummaryProps) => { const scoreTextColor = getScoreTextColor(score); return ( -
+

From a8dc24334de9a7aec36bb7450ba2e1e1f35b6d5f Mon Sep 17 00:00:00 2001 From: Adrian Machado Date: Fri, 22 Sep 2023 16:39:37 -0700 Subject: [PATCH 4/7] Log the summary --- apps/web/src/app/report/[id]/report-summary.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/web/src/app/report/[id]/report-summary.tsx b/apps/web/src/app/report/[id]/report-summary.tsx index 9b800ff..f0c0505 100644 --- a/apps/web/src/app/report/[id]/report-summary.tsx +++ b/apps/web/src/app/report/[id]/report-summary.tsx @@ -6,6 +6,7 @@ type ReportSummaryProps = { }; const ReportSummary = ({ summary, score }: ReportSummaryProps) => { + console.log("Summary raw", summary); const scoreTextColor = getScoreTextColor(score); return (
From 2b1a804df96ba4c9e5d1eb244b0ef18b840ad6d6 Mon Sep 17 00:00:00 2001 From: Adrian Machado Date: Fri, 22 Sep 2023 16:48:13 -0700 Subject: [PATCH 5/7] Try to preserve spacing --- apps/web/src/app/report/[id]/report-summary.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/app/report/[id]/report-summary.tsx b/apps/web/src/app/report/[id]/report-summary.tsx index f0c0505..a4871ca 100644 --- a/apps/web/src/app/report/[id]/report-summary.tsx +++ b/apps/web/src/app/report/[id]/report-summary.tsx @@ -15,7 +15,7 @@ const ReportSummary = ({ summary, score }: ReportSummaryProps) => { > Summary (AI Generated)

-

{summary}

+

{summary}

); }; From f4543800e47a229b3e07b39dd9289d798fcdb11f Mon Sep 17 00:00:00 2001 From: Adrian Machado Date: Mon, 25 Sep 2023 12:14:25 -0700 Subject: [PATCH 6/7] Add a short summary and long summary --- apps/api/src/lib/rating.ts | 63 ++++++++++++++----- apps/web/src/app/report/[id]/page.tsx | 5 +- .../src/app/report/[id]/report-summary.tsx | 24 +++++-- .../app/report/[id]/simple-report-request.ts | 3 +- 4 files changed, 70 insertions(+), 25 deletions(-) diff --git a/apps/api/src/lib/rating.ts b/apps/api/src/lib/rating.ts index 2e1a70a..e251143 100644 --- a/apps/api/src/lib/rating.ts +++ b/apps/api/src/lib/rating.ts @@ -29,6 +29,10 @@ type GenerateRatingInput = { fileExtension: "json" | "yaml"; }; +/** + * @description produces a stripped down version of the report which can be fed + * to LLM models. + */ const getReportMinified = (fullReport: RatingOutput) => { const issues = fullReport.issues; return issues @@ -57,32 +61,53 @@ const getReportMinified = (fullReport: RatingOutput) => { ); }; -const getOpenAiSummary = async (issueSummary: object) => { +const getOpenAiResponse = async ( + messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[], +) => { const response = await openai.chat.completions.create({ model: "gpt-3.5-turbo", - messages: [ - { - role: "system", - content: - "You are an expert in REST API Development and know everything about OpenAPI and what makes a good API. You like chatting in a playful, and a somewhat snarky manner. Don't make fun of the user though.", - }, - { - role: "user", - content: `Here's a summary of issues found in an OpenAPI file. The format is a JSON, where the first level indicates the severity of the issue (the lower the key, the more severe), the second level is the name of the issue. These mostly match up to existing spectral rulesets, so you can infer what the issue is. The third level contains the number of occurrences of that issue.\n\nI would like a succinct summary of the issues and advice on how to fix them. Focus on the most common issues and the highest severity. Keep the tone casual and playful, and a bit snarky. Also, no bullet points. Maximum of 3 issues please. Rank by severity and then occurrences.\n\nHere's the issue summary\n ${JSON.stringify( - issueSummary, - )}`, - }, - ], + messages, temperature: 0.5, max_tokens: 400, top_p: 1, frequency_penalty: 0, presence_penalty: 0, }); - console.log("response", response); return response.choices[0].message.content; }; +const getOpenAiLongSummary = async (issueSummary: object) => { + return await getOpenAiResponse([ + { + role: "system", + content: + "You are an expert in REST API Development and know everything about OpenAPI and what makes a good API. You like chatting in a playful, and a somewhat snarky manner. Don't make fun of the user though.", + }, + { + role: "user", + content: `Here's a summary of issues found in an OpenAPI file. The format is a JSON, where the first level indicates the severity of the issue (the lower the key, the more severe), the second level is the name of the issue. These mostly match up to existing spectral rulesets, so you can infer what the issue is. The third level contains the number of occurrences of that issue.\n\nI would like a succinct summary of the issues and advice on how to fix them. Focus on the most common issues and the highest severity. Keep the tone casual and playful, and a bit snarky. Also, no bullet points. Maximum of 3 issues please. Rank by severity and then occurrences.\n\nHere's the issue summary\n ${JSON.stringify( + issueSummary, + )}`, + }, + ]); +}; + +const getOpenAiShortSummary = async (issueSummary: object) => { + return await getOpenAiResponse([ + { + role: "system", + content: + "You are an expert in REST API Development and know everything about OpenAPI and what makes a good API. You like chatting in a playful, and a somewhat snarky manner. Don't make fun of the user though.", + }, + { + role: "user", + content: `Here's a summary of issues found in an OpenAPI file. The format is a JSON, where the first level indicates the severity of the issue (the lower the key, the more severe), the second level is the name of the issue. These mostly match up to existing spectral rulesets, so you can infer what the issue is. The third level contains the number of occurrences of that issue.\n\nI would like a succinct summary of the issues in 2 lines. Keep the tone casual and playful, and a bit snarky. Do not insult the user or API creator or the API. Also, no bullet points. Only talk about the highest severity issues.\n\nHere's the issue summary\n ${JSON.stringify( + issueSummary, + )}`, + }, + ]); +}; + export const uploadReport = async ({ reportId, fullReport, @@ -331,7 +356,10 @@ const getReport = async ( } const issueSummary = getReportMinified(output); - const openAiSummary = await getOpenAiSummary(issueSummary); + const [openAiLongSummary, openAiShortSummary] = await Promise.all([ + getOpenAiLongSummary(issueSummary), + getOpenAiShortSummary(issueSummary), + ]); const simpleReport = { version: // TODO: Clean this up @@ -350,7 +378,8 @@ const getReport = async ( score: output.score, securityScore: output.securityScore, sdkGenerationScore: output.sdkGenerationScore, - summary: openAiSummary ?? undefined, + shortSummary: openAiShortSummary ?? undefined, + longSummary: openAiLongSummary ?? undefined, }; return Ok({ diff --git a/apps/web/src/app/report/[id]/page.tsx b/apps/web/src/app/report/[id]/page.tsx index 085386d..cdb24bd 100644 --- a/apps/web/src/app/report/[id]/page.tsx +++ b/apps/web/src/app/report/[id]/page.tsx @@ -38,9 +38,10 @@ const ReportPage = async ({ params }: { params: { id: string } }) => { return ( <> - {simpleReport.summary ? ( + {simpleReport.shortSummary && simpleReport.longSummary ? ( ) : null} diff --git a/apps/web/src/app/report/[id]/report-summary.tsx b/apps/web/src/app/report/[id]/report-summary.tsx index a4871ca..39e5b9e 100644 --- a/apps/web/src/app/report/[id]/report-summary.tsx +++ b/apps/web/src/app/report/[id]/report-summary.tsx @@ -1,21 +1,35 @@ import getScoreTextColor from "@/utils/get-score-test-color"; +import { useState } from "react"; type ReportSummaryProps = { - summary: string; + shortSummary: string; + longSummary: string; score: number; }; -const ReportSummary = ({ summary, score }: ReportSummaryProps) => { - console.log("Summary raw", summary); +const ReportSummary = ({ + shortSummary, + longSummary, + score, +}: ReportSummaryProps) => { + const [isExpanded, setIsExpanded] = useState(false); const scoreTextColor = getScoreTextColor(score); return (

- Summary (AI Generated) + Summary

-

{summary}

+

+ {isExpanded ? longSummary : shortSummary} +

+
); }; diff --git a/apps/web/src/app/report/[id]/simple-report-request.ts b/apps/web/src/app/report/[id]/simple-report-request.ts index 387cf84..72a6465 100644 --- a/apps/web/src/app/report/[id]/simple-report-request.ts +++ b/apps/web/src/app/report/[id]/simple-report-request.ts @@ -7,7 +7,8 @@ export type SimpleReport = { fileExtension: "json" | "yaml"; title: string; version: string; - summary?: string; + shortSummary?: string; + longSummary?: string; }; export const getSimpleReport = async ( From cbb15e95199deee7095f1c099423a7210b738b38 Mon Sep 17 00:00:00 2001 From: Adrian Machado Date: Mon, 25 Sep 2023 12:19:01 -0700 Subject: [PATCH 7/7] Change to client component --- apps/web/src/app/report/[id]/report-summary.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/web/src/app/report/[id]/report-summary.tsx b/apps/web/src/app/report/[id]/report-summary.tsx index 39e5b9e..ecd8e01 100644 --- a/apps/web/src/app/report/[id]/report-summary.tsx +++ b/apps/web/src/app/report/[id]/report-summary.tsx @@ -1,3 +1,5 @@ +"use client"; + import getScoreTextColor from "@/utils/get-score-test-color"; import { useState } from "react";