Skip to content

Commit

Permalink
feat: ai summary widget
Browse files Browse the repository at this point in the history
  • Loading branch information
Innei committed Aug 18, 2023
1 parent 082cf02 commit 877f04f
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 8 deletions.
14 changes: 6 additions & 8 deletions src/app/api/ai/summary/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import OpenAI from 'openai'
import type { ArticleDataType } from '~/types/api'
import type { NextRequest } from 'next/server'

import { sql } from '@vercel/postgres'
Expand All @@ -16,13 +17,7 @@ export const GET = async (req: NextRequest) => {
const dataString = searchParams.get('data') as string
const lang = searchParams.get('lang') || ('zh' as string)

let data:
| { type: 'post'; category: string; slug: string }
| { type: 'note'; nid: number }
| {
type: 'page'
slug: string
}
let data: ArticleDataType

try {
data = JSON.parse(decodeURIComponent(dataString))
Expand Down Expand Up @@ -87,7 +82,10 @@ export const GET = async (req: NextRequest) => {
messages: [
{
role: 'user',
content: `Summarize the following and use a third person description in ${lang} : ${text}`,
content: `Summarize this in "${lang}" language:
"${text}"
CONCISE SUMMARY:`,
},
],
model: 'gpt-3.5-turbo',
Expand Down
1 change: 1 addition & 0 deletions src/app/notes/[id]/pageImpl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const NotePage = function (props: NoteModel) {

<NoteHideIfSecret>
<XLogSummary cid={getCidForBaseModel(props)} />
{/* <AISummary data={props} /> */}
<WrappedElementProvider>
<ReadIndicatorForMobile />
<NoteMarkdownImageRecordProvider>
Expand Down
102 changes: 102 additions & 0 deletions src/components/widgets/ai/Summary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
'use client'

import { useQuery } from '@tanstack/react-query'
import { useMemo } from 'react'
import type { NoteModel, PageModel, PostModel } from '@mx-space/api-client'
import type { ArticleDataType } from '~/types/api'
import type { FC, ReactNode } from 'react'

import { AutoResizeHeight } from '~/components/widgets/shared/AutoResizeHeight'
import { API_URL } from '~/constants/env'
import { clsxm } from '~/lib/helper'
import { isNoteModel, isPageModel, isPostModel } from '~/lib/url-builder'

export const AISummary: FC<{
data: PostModel | NoteModel | PageModel
className?: string
}> = (props) => {
const { data } = props

const payload = useMemo(() => {
let payload: ArticleDataType

if (isPostModel(data)) {
payload = {
category: data.category.slug,
slug: data.slug,
type: 'post',
}
} else if (isNoteModel(data)) {
payload = {
nid: data.nid,
type: 'note',
}
} else if (isPageModel(data)) {
payload = {
slug: data.slug,
type: 'page',
}
} else {
throw new Error('未知类型')
}

return payload
}, [data])
const { data: response, isLoading } = useQuery<{
summary: string
source: string
}>(
[`ai-summary`, data.id, API_URL, data.modified],
async () => {
const data = await fetch(
`/api/ai/summary?data=${encodeURIComponent(JSON.stringify(payload))}`,
{
next: {
revalidate: 60 * 10,
},
},
).then((res) => res.json())
if (!data) throw new Error('请求错误')
return data
},
{
staleTime: 1000 * 60 * 60 * 24 * 7,
retryDelay: 5000,
},
)

const Inner: ReactNode = (
<div
data-hide-print
className={clsxm(
`space-y-2 rounded-xl border border-slate-200 p-4 dark:border-neutral-800`,
props.className,
)}
>
<div className="flex items-center">
<i className="icon-[mingcute--sparkles-line] mr-2 text-lg" />
AI 生成的摘要
</div>

<AutoResizeHeight duration={0.3}>
<p className="text-base-content/85 !m-0 text-sm leading-loose">
{isLoading ? (
<div className="space-y-2">
<span className="block h-5 w-full animate-pulse rounded-xl bg-zinc-200 dark:bg-neutral-800" />
<span className="block h-5 w-full animate-pulse rounded-xl bg-zinc-200 dark:bg-neutral-800" />
<span className="block h-5 w-full animate-pulse rounded-xl bg-zinc-200 dark:bg-neutral-800" />
</div>
) : (
response?.summary
)}
</p>
</AutoResizeHeight>
</div>
)

return (
<AutoResizeHeight duration={0.2} className="mt-4">
{Inner}
</AutoResizeHeight>
)
}
1 change: 1 addition & 0 deletions src/components/widgets/xlog/XLogSummaryRSC.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const fetchData = async (cid: string, lang = 'zh') => {
.then((res) => res.json())
.catch(() => null)
}

export const XLogSummary = async (
props: ComponentType<{
cid: string
Expand Down
14 changes: 14 additions & 0 deletions src/types/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export type ArticleDataType =
| {
type: 'post'
category: string
slug: string
}
| {
type: 'note'
nid: number
}
| {
type: 'page'
slug: string
}

1 comment on commit 877f04f

@vercel
Copy link

@vercel vercel bot commented on 877f04f Aug 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

shiro – ./

shiro-innei.vercel.app
springtide.vercel.app
innei.in
shiro-git-main-innei.vercel.app

Please sign in to comment.