feat(search): Add searchUrl to message

This commit is contained in:
Willie Zutz 2025-05-07 23:35:07 -06:00
parent 641968cf6a
commit bdace57cfd
5 changed files with 51 additions and 10 deletions

View file

@ -66,6 +66,7 @@ const handleEmitterEvents = async (
let recievedMessage = '';
let sources: any[] = [];
let searchQuery: string | undefined;
let searchUrl: string | undefined;
stream.on('data', (data) => {
const parsedData = JSON.parse(data);
@ -86,6 +87,9 @@ const handleEmitterEvents = async (
if (parsedData.searchQuery) {
searchQuery = parsedData.searchQuery;
}
if (parsedData.searchUrl) {
searchUrl = parsedData.searchUrl;
}
writer.write(
encoder.encode(
@ -94,6 +98,7 @@ const handleEmitterEvents = async (
data: parsedData.data,
searchQuery: parsedData.searchQuery,
messageId: aiMessageId,
searchUrl: searchUrl,
}) + '\n',
),
);
@ -128,6 +133,7 @@ const handleEmitterEvents = async (
messageId: aiMessageId,
modelStats: modelStats,
searchQuery: searchQuery,
searchUrl: searchUrl,
}) + '\n',
),
);
@ -144,6 +150,7 @@ const handleEmitterEvents = async (
...(sources && sources.length > 0 && { sources }),
...(searchQuery && { searchQuery }),
modelStats: modelStats,
...(searchUrl && { searchUrl }),
}),
})
.execute();

View file

@ -28,6 +28,7 @@ export type Message = {
sources?: Document[];
modelStats?: ModelStats;
searchQuery?: string;
searchUrl?: string;
};
export interface File {
@ -417,7 +418,6 @@ const ChatWindow = ({ id }: { id?: string }) => {
if (data.type === 'sources') {
sources = data.data;
const searchQuery = data.searchQuery;
if (!added) {
setMessages((prevMessages) => [
...prevMessages,
@ -427,7 +427,8 @@ const ChatWindow = ({ id }: { id?: string }) => {
chatId: chatId!,
role: 'assistant',
sources: sources,
searchQuery: searchQuery,
searchQuery: data.searchQuery,
searchUrl: data.searchUrl,
createdAt: new Date(),
},
]);
@ -486,6 +487,7 @@ const ChatWindow = ({ id }: { id?: string }) => {
modelStats: data.modelStats || null,
// Make sure the searchQuery is preserved (if available in the message data)
searchQuery: message.searchQuery || data.searchQuery,
searchUrl: message.searchUrl || data.searchUrl,
};
}
return message;

View file

@ -283,9 +283,20 @@ const MessageBox = ({
<span className="font-medium text-black/70 dark:text-white/70">
Search query:
</span>{' '}
<span className="text-black dark:text-white">
{message.searchQuery}
</span>
{message.searchUrl ? (
<a
href={message.searchUrl}
target="_blank"
rel="noopener noreferrer"
className="dark:text-white text-black hover:underline"
>
{message.searchQuery}
</a>
) : (
<span className="text-black dark:text-white">
{message.searchQuery}
</span>
)}
</div>
)}
<MessageSources sources={message.sources} />

View file

@ -56,6 +56,7 @@ class MetaSearchAgent implements MetaSearchAgentType {
private config: Config;
private strParser = new StringOutputParser();
private searchQuery?: string;
private searxngUrl?: string;
constructor(config: Config) {
this.config = config;
@ -81,6 +82,7 @@ class MetaSearchAgent implements MetaSearchAgentType {
let question = this.config.summarizer
? await questionOutputParser.parse(input)
: input;
console.log('question', question);
if (question === 'not_needed') {
return { query: '', docs: [] };
@ -206,12 +208,15 @@ class MetaSearchAgent implements MetaSearchAgentType {
} else {
question = question.replace(/<think>.*?<\/think>/g, '');
const res = await searchSearxng(question, {
const searxngResult = await searchSearxng(question, {
language: 'en',
engines: this.config.activeEngines,
});
const documents = res.results.map(
// Store the SearXNG URL for later use in emitting to the client
this.searxngUrl = searxngResult.searchUrl;
const documents = searxngResult.results.map(
(result) =>
new Document({
pageContent:
@ -447,9 +452,7 @@ class MetaSearchAgent implements MetaSearchAgentType {
event.event === 'on_chain_end' &&
event.name === 'FinalSourceRetriever'
) {
// Add searchQuery to the sources data if it exists
const sourcesData = event.data.output;
// @ts-ignore - we added searchQuery property
if (this.searchQuery) {
emitter.emit(
'data',
@ -457,6 +460,7 @@ class MetaSearchAgent implements MetaSearchAgentType {
type: 'sources',
data: sourcesData,
searchQuery: this.searchQuery,
searchUrl: this.searxngUrl,
}),
);
} else {

View file

@ -19,6 +19,12 @@ interface SearxngSearchResult {
iframe_src?: string;
}
interface SearxngResponse {
results: SearxngSearchResult[];
suggestions: string[];
searchUrl: string;
}
export const searchSearxng = async (
query: string,
opts?: SearxngSearchOptions,
@ -44,5 +50,16 @@ export const searchSearxng = async (
const results: SearxngSearchResult[] = res.data.results;
const suggestions: string[] = res.data.suggestions;
return { results, suggestions };
// Create a URL for viewing the search results in the SearXNG web interface
const searchUrl = new URL(searxngURL);
searchUrl.pathname = '/search';
searchUrl.searchParams.append('q', query);
if (opts?.engines?.length) {
searchUrl.searchParams.append('engines', opts.engines.join(','));
}
if (opts?.language) {
searchUrl.searchParams.append('language', opts.language);
}
return { results, suggestions, searchUrl: searchUrl.toString() };
};