mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-12-03 18:28:15 +00:00
feat(widgets): add LLM context to prevent context overflow
This commit is contained in:
@@ -65,14 +65,13 @@ class SearchAgent {
|
|||||||
|
|
||||||
const widgetContext = widgetOutputs
|
const widgetContext = widgetOutputs
|
||||||
.map((o) => {
|
.map((o) => {
|
||||||
return `${o.type}: ${JSON.stringify(o.data)}`;
|
return `${o.type}: ${o.llmContext}`;
|
||||||
})
|
})
|
||||||
.join('\n-------------\n');
|
.join('\n-------------\n');
|
||||||
|
|
||||||
const finalContextWithWidgets = `<search_results note="These are the search results and you can cite these">${finalContext}</search_results>\n<widgets_result noteForAssistant="Its output is already showed to the user, you can use this information to answer the query but do not CITE this as a souce">${widgetContext}</widgets_result>`;
|
const finalContextWithWidgets = `<search_results note="These are the search results and you can cite these">${finalContext}</search_results>\n<widgets_result noteForAssistant="Its output is already showed to the user, you can use this information to answer the query but do not CITE this as a souce">${widgetContext}</widgets_result>`;
|
||||||
|
|
||||||
const writerPrompt = getWriterPrompt(finalContextWithWidgets);
|
const writerPrompt = getWriterPrompt(finalContextWithWidgets);
|
||||||
|
|
||||||
const answerStream = input.config.llm.streamText({
|
const answerStream = input.config.llm.streamText({
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export type WidgetConfig = {
|
|||||||
|
|
||||||
export type WidgetOutput = {
|
export type WidgetOutput = {
|
||||||
type: string;
|
type: string;
|
||||||
|
llmContext: string;
|
||||||
data: any;
|
data: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ const calculationWidget: Widget<typeof schema> = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'calculation_result',
|
type: 'calculation_result',
|
||||||
|
llmContext: `The result of the expression "${params.expression}" is ${result}.`,
|
||||||
data: {
|
data: {
|
||||||
expression: params.expression,
|
expression: params.expression,
|
||||||
result: result,
|
result: result,
|
||||||
@@ -53,6 +54,7 @@ const calculationWidget: Widget<typeof schema> = {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
type: 'calculation_result',
|
type: 'calculation_result',
|
||||||
|
llmContext: 'Failed to evaluate mathematical expression.',
|
||||||
data: {
|
data: {
|
||||||
expression: params.expression,
|
expression: params.expression,
|
||||||
result: `Error evaluating expression: ${error}`,
|
result: `Error evaluating expression: ${error}`,
|
||||||
|
|||||||
@@ -286,120 +286,129 @@ You can set skipSearch to true if the stock widget can fully answer the user's q
|
|||||||
chartData: {
|
chartData: {
|
||||||
'1D': chart1D
|
'1D': chart1D
|
||||||
? {
|
? {
|
||||||
timestamps: chart1D.quotes.map((q: any) => q.date.getTime()),
|
timestamps: chart1D.quotes.map((q: any) => q.date.getTime()),
|
||||||
prices: chart1D.quotes.map((q: any) => q.close),
|
prices: chart1D.quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
'5D': chart5D
|
'5D': chart5D
|
||||||
? {
|
? {
|
||||||
timestamps: chart5D.quotes.map((q: any) => q.date.getTime()),
|
timestamps: chart5D.quotes.map((q: any) => q.date.getTime()),
|
||||||
prices: chart5D.quotes.map((q: any) => q.close),
|
prices: chart5D.quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
'1M': chart1M
|
'1M': chart1M
|
||||||
? {
|
? {
|
||||||
timestamps: chart1M.quotes.map((q: any) => q.date.getTime()),
|
timestamps: chart1M.quotes.map((q: any) => q.date.getTime()),
|
||||||
prices: chart1M.quotes.map((q: any) => q.close),
|
prices: chart1M.quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
'3M': chart3M
|
'3M': chart3M
|
||||||
? {
|
? {
|
||||||
timestamps: chart3M.quotes.map((q: any) => q.date.getTime()),
|
timestamps: chart3M.quotes.map((q: any) => q.date.getTime()),
|
||||||
prices: chart3M.quotes.map((q: any) => q.close),
|
prices: chart3M.quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
'6M': chart6M
|
'6M': chart6M
|
||||||
? {
|
? {
|
||||||
timestamps: chart6M.quotes.map((q: any) => q.date.getTime()),
|
timestamps: chart6M.quotes.map((q: any) => q.date.getTime()),
|
||||||
prices: chart6M.quotes.map((q: any) => q.close),
|
prices: chart6M.quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
'1Y': chart1Y
|
'1Y': chart1Y
|
||||||
? {
|
? {
|
||||||
timestamps: chart1Y.quotes.map((q: any) => q.date.getTime()),
|
timestamps: chart1Y.quotes.map((q: any) => q.date.getTime()),
|
||||||
prices: chart1Y.quotes.map((q: any) => q.close),
|
prices: chart1Y.quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
MAX: chartMAX
|
MAX: chartMAX
|
||||||
? {
|
? {
|
||||||
timestamps: chartMAX.quotes.map((q: any) => q.date.getTime()),
|
timestamps: chartMAX.quotes.map((q: any) => q.date.getTime()),
|
||||||
prices: chartMAX.quotes.map((q: any) => q.close),
|
prices: chartMAX.quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
},
|
},
|
||||||
comparisonData: comparisonData
|
comparisonData: comparisonData
|
||||||
? comparisonData.map((comp: any) => ({
|
? comparisonData.map((comp: any) => ({
|
||||||
ticker: comp.ticker,
|
ticker: comp.ticker,
|
||||||
name: comp.name,
|
name: comp.name,
|
||||||
chartData: {
|
chartData: {
|
||||||
'1D': comp.charts[0]
|
'1D': comp.charts[0]
|
||||||
? {
|
? {
|
||||||
timestamps: comp.charts[0].quotes.map((q: any) =>
|
timestamps: comp.charts[0].quotes.map((q: any) =>
|
||||||
q.date.getTime(),
|
q.date.getTime(),
|
||||||
),
|
),
|
||||||
prices: comp.charts[0].quotes.map((q: any) => q.close),
|
prices: comp.charts[0].quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
'5D': comp.charts[1]
|
'5D': comp.charts[1]
|
||||||
? {
|
? {
|
||||||
timestamps: comp.charts[1].quotes.map((q: any) =>
|
timestamps: comp.charts[1].quotes.map((q: any) =>
|
||||||
q.date.getTime(),
|
q.date.getTime(),
|
||||||
),
|
),
|
||||||
prices: comp.charts[1].quotes.map((q: any) => q.close),
|
prices: comp.charts[1].quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
'1M': comp.charts[2]
|
'1M': comp.charts[2]
|
||||||
? {
|
? {
|
||||||
timestamps: comp.charts[2].quotes.map((q: any) =>
|
timestamps: comp.charts[2].quotes.map((q: any) =>
|
||||||
q.date.getTime(),
|
q.date.getTime(),
|
||||||
),
|
),
|
||||||
prices: comp.charts[2].quotes.map((q: any) => q.close),
|
prices: comp.charts[2].quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
'3M': comp.charts[3]
|
'3M': comp.charts[3]
|
||||||
? {
|
? {
|
||||||
timestamps: comp.charts[3].quotes.map((q: any) =>
|
timestamps: comp.charts[3].quotes.map((q: any) =>
|
||||||
q.date.getTime(),
|
q.date.getTime(),
|
||||||
),
|
),
|
||||||
prices: comp.charts[3].quotes.map((q: any) => q.close),
|
prices: comp.charts[3].quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
'6M': comp.charts[4]
|
'6M': comp.charts[4]
|
||||||
? {
|
? {
|
||||||
timestamps: comp.charts[4].quotes.map((q: any) =>
|
timestamps: comp.charts[4].quotes.map((q: any) =>
|
||||||
q.date.getTime(),
|
q.date.getTime(),
|
||||||
),
|
),
|
||||||
prices: comp.charts[4].quotes.map((q: any) => q.close),
|
prices: comp.charts[4].quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
'1Y': comp.charts[5]
|
'1Y': comp.charts[5]
|
||||||
? {
|
? {
|
||||||
timestamps: comp.charts[5].quotes.map((q: any) =>
|
timestamps: comp.charts[5].quotes.map((q: any) =>
|
||||||
q.date.getTime(),
|
q.date.getTime(),
|
||||||
),
|
),
|
||||||
prices: comp.charts[5].quotes.map((q: any) => q.close),
|
prices: comp.charts[5].quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
MAX: comp.charts[6]
|
MAX: comp.charts[6]
|
||||||
? {
|
? {
|
||||||
timestamps: comp.charts[6].quotes.map((q: any) =>
|
timestamps: comp.charts[6].quotes.map((q: any) =>
|
||||||
q.date.getTime(),
|
q.date.getTime(),
|
||||||
),
|
),
|
||||||
prices: comp.charts[6].quotes.map((q: any) => q.close),
|
prices: comp.charts[6].quotes.map((q: any) => q.close),
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
: null,
|
: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'stock',
|
type: 'stock',
|
||||||
|
llmContext: `Current price of ${stockData.shortName} (${stockData.symbol}) is ${stockData.regularMarketPrice} ${stockData.currency}. Other details: ${JSON.stringify({
|
||||||
|
marketState: stockData.marketState,
|
||||||
|
regularMarketChange: stockData.regularMarketChange,
|
||||||
|
regularMarketChangePercent: stockData.regularMarketChangePercent,
|
||||||
|
marketCap: stockData.marketCap,
|
||||||
|
peRatio: stockData.trailingPE,
|
||||||
|
dividendYield: stockData.dividendYield,
|
||||||
|
})}`,
|
||||||
data: stockData,
|
data: stockData,
|
||||||
};
|
};
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return {
|
return {
|
||||||
type: 'stock',
|
type: 'stock',
|
||||||
|
llmContext: 'Failed to fetch stock data.',
|
||||||
data: {
|
data: {
|
||||||
error: `Error fetching stock data: ${error.message || error}`,
|
error: `Error fetching stock data: ${error.message || error}`,
|
||||||
ticker: params.ticker,
|
ticker: params.ticker,
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ You can set skipSearch to true if the weather widget can fully answer the user's
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'weather',
|
type: 'weather',
|
||||||
|
llmContext: `Weather in ${params.location} is ${weatherData.current}`,
|
||||||
data: {
|
data: {
|
||||||
location: params.location,
|
location: params.location,
|
||||||
latitude: location.lat,
|
latitude: location.lat,
|
||||||
@@ -138,6 +139,7 @@ You can set skipSearch to true if the weather widget can fully answer the user's
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'weather',
|
type: 'weather',
|
||||||
|
llmContext: `Weather in ${locationData.display_name} is ${weatherData.current}`,
|
||||||
data: {
|
data: {
|
||||||
location: locationData.display_name,
|
location: locationData.display_name,
|
||||||
latitude: params.lat,
|
latitude: params.lat,
|
||||||
@@ -159,11 +161,13 @@ You can set skipSearch to true if the weather widget can fully answer the user's
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'weather',
|
type: 'weather',
|
||||||
|
llmContext: 'No valid location or coordinates provided.',
|
||||||
data: null,
|
data: null,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return {
|
return {
|
||||||
type: 'weather',
|
type: 'weather',
|
||||||
|
llmContext: 'Failed to fetch weather data.',
|
||||||
data: {
|
data: {
|
||||||
error: `Error fetching weather data: ${err}`,
|
error: `Error fetching weather data: ${err}`,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user