mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-28 21:18:57 +00:00
Cache AI Page Link summary (#3106)
Co-authored-by: Samy Pessé <samypesse@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
Cache AI Page Link summary
|
||||
@@ -3,11 +3,32 @@ import { useLanguage } from '@/intl/client';
|
||||
import { t } from '@/intl/translate';
|
||||
import { Icon } from '@gitbook/icons';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { create } from 'zustand';
|
||||
import { useVisitedPages } from '../Insights';
|
||||
import { usePageContext } from '../PageContext';
|
||||
import { Loading } from '../primitives';
|
||||
import { streamLinkPageSummary } from './server-actions/streamLinkPageSummary';
|
||||
|
||||
const useSummaries = create<{
|
||||
cache: Map<string, string>;
|
||||
setSummary: (key: string, summary: string) => void;
|
||||
}>((set) => ({
|
||||
cache: new Map(),
|
||||
setSummary: (key, summary) =>
|
||||
set((state) => {
|
||||
const newCache = new Map(state.cache);
|
||||
newCache.set(key, summary);
|
||||
return { cache: newCache };
|
||||
}),
|
||||
}));
|
||||
|
||||
/**
|
||||
* Get a unique cache key for a page summary
|
||||
*/
|
||||
function getCacheKey(targetSpaceId: string, targetPageId: string): string {
|
||||
return `${targetSpaceId}:${targetPageId}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarise a page's content for use in a link preview
|
||||
*/
|
||||
@@ -21,15 +42,26 @@ export function AIPageLinkSummary(props: {
|
||||
const { targetSpaceId, targetPageId, linkPreview, linkTitle, showTrademark = true } = props;
|
||||
|
||||
const currentPage = usePageContext();
|
||||
|
||||
const language = useLanguage();
|
||||
const visitedPages = useVisitedPages((state) => state.pages);
|
||||
const [highlight, setHighlight] = useState('');
|
||||
const [summary, setSummary] = useState('');
|
||||
const cacheKey = getCacheKey(targetSpaceId, targetPageId);
|
||||
const { cachedSummary, setCachedSummary } = useSummaries((state) => {
|
||||
return {
|
||||
cachedSummary: state.cache.get(cacheKey) ?? '',
|
||||
setCachedSummary: state.setSummary,
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
let canceled = false;
|
||||
|
||||
setHighlight('');
|
||||
setSummary('');
|
||||
|
||||
if (cachedSummary) {
|
||||
setSummary(cachedSummary);
|
||||
return;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const stream = await streamLinkPageSummary({
|
||||
@@ -43,9 +75,16 @@ export function AIPageLinkSummary(props: {
|
||||
visitedPages,
|
||||
});
|
||||
|
||||
let generatedSummary = '';
|
||||
for await (const highlight of stream) {
|
||||
if (canceled) return;
|
||||
setHighlight(highlight ?? '');
|
||||
generatedSummary = highlight ?? '';
|
||||
setSummary(generatedSummary);
|
||||
}
|
||||
|
||||
// Cache the complete summary
|
||||
if (generatedSummary) {
|
||||
setCachedSummary(cacheKey, generatedSummary);
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -61,6 +100,9 @@ export function AIPageLinkSummary(props: {
|
||||
linkPreview,
|
||||
linkTitle,
|
||||
visitedPages,
|
||||
cachedSummary,
|
||||
cacheKey,
|
||||
setCachedSummary,
|
||||
]);
|
||||
|
||||
const shimmerBlocks = [
|
||||
@@ -76,14 +118,14 @@ export function AIPageLinkSummary(props: {
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="flex w-screen items-center gap-1 font-semibold text-tint text-xs uppercase leading-tight tracking-wide">
|
||||
{showTrademark ? (
|
||||
<Loading className="size-4" busy={!highlight || highlight.length === 0} />
|
||||
<Loading className="size-4" busy={!summary || summary.length === 0} />
|
||||
) : (
|
||||
<Icon icon="sparkle" className="size-3" />
|
||||
)}
|
||||
<h6 className="text-tint">{t(language, 'link_tooltip_ai_summary')}</h6>
|
||||
</div>
|
||||
{highlight.length > 0 ? (
|
||||
<p className="animate-fadeIn">{highlight}</p>
|
||||
{summary.length > 0 ? (
|
||||
<p className="animate-fadeIn">{summary}</p>
|
||||
) : (
|
||||
<div className="mt-2 flex flex-wrap gap-2">
|
||||
{shimmerBlocks.map((block, index) => (
|
||||
@@ -94,7 +136,7 @@ export function AIPageLinkSummary(props: {
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{highlight.length > 0 ? (
|
||||
{summary.length > 0 ? (
|
||||
<div className="animate-fadeIn text-tint-subtle text-xs">
|
||||
{t(language, 'link_tooltip_ai_summary_description')}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user