chore: cleanup unused ResearchStep
params
This commit is contained in:
@ -3,13 +3,11 @@
|
|||||||
import type { TreeNode } from './Tree.vue'
|
import type { TreeNode } from './Tree.vue'
|
||||||
|
|
||||||
const tree = ref<TreeNode>({
|
const tree = ref<TreeNode>({
|
||||||
id: 'root',
|
id: '0',
|
||||||
label: 'Start',
|
label: 'Start',
|
||||||
children: [],
|
children: [],
|
||||||
depth: 0,
|
|
||||||
breadth: 0,
|
|
||||||
})
|
})
|
||||||
const hoveredNode = ref<TreeNode | null>(null)
|
const selectedNode = ref<TreeNode | null>(null)
|
||||||
const searchResults = ref<Record<string, PartialSearchResult>>({})
|
const searchResults = ref<Record<string, PartialSearchResult>>({})
|
||||||
|
|
||||||
const modelValue = computed(() => Object.values(searchResults.value))
|
const modelValue = computed(() => Object.values(searchResults.value))
|
||||||
@ -32,9 +30,6 @@
|
|||||||
if (!node) {
|
if (!node) {
|
||||||
console.error('Creating new node', {
|
console.error('Creating new node', {
|
||||||
nodeId,
|
nodeId,
|
||||||
depth: step.depth,
|
|
||||||
breadth: step.breadth,
|
|
||||||
index: step.nodeIndex,
|
|
||||||
})
|
})
|
||||||
// 创建新节点
|
// 创建新节点
|
||||||
node = {
|
node = {
|
||||||
@ -43,12 +38,10 @@
|
|||||||
researchGoal: 'Generating research goal...',
|
researchGoal: 'Generating research goal...',
|
||||||
learnings: [],
|
learnings: [],
|
||||||
children: [],
|
children: [],
|
||||||
depth: step.depth,
|
|
||||||
breadth: step.breadth,
|
|
||||||
index: step.nodeIndex,
|
|
||||||
}
|
}
|
||||||
|
const parentNodeId = getParentNodeId(nodeId)
|
||||||
// 如果是根节点的直接子节点
|
// 如果是根节点的直接子节点
|
||||||
if (step.depth === 1) {
|
if (parentNodeId === '0') {
|
||||||
tree.value.children.push(node)
|
tree.value.children.push(node)
|
||||||
} else {
|
} else {
|
||||||
// 找到父节点并添加
|
// 找到父节点并添加
|
||||||
@ -81,6 +74,7 @@
|
|||||||
|
|
||||||
case 'search_complete': {
|
case 'search_complete': {
|
||||||
if (node) {
|
if (node) {
|
||||||
|
node.visitedUrls = step.urls
|
||||||
// node.label = `Found ${step.urls.length} results for: ${node.query}`
|
// node.label = `Found ${step.urls.length} results for: ${node.query}`
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@ -90,7 +84,6 @@
|
|||||||
if (node) {
|
if (node) {
|
||||||
node.learnings = step.result.learnings || []
|
node.learnings = step.result.learnings || []
|
||||||
node.followUpQuestions = step.result.followUpQuestions || []
|
node.followUpQuestions = step.result.followUpQuestions || []
|
||||||
// node.label = `Processing results: ${node.query}`
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -98,7 +91,6 @@
|
|||||||
case 'processed_search_result': {
|
case 'processed_search_result': {
|
||||||
if (node) {
|
if (node) {
|
||||||
node.learnings = step.result.learnings
|
node.learnings = step.result.learnings
|
||||||
// node.label = `Completed: ${node.query}`
|
|
||||||
searchResults.value[nodeId] = step.result
|
searchResults.value[nodeId] = step.result
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@ -144,9 +136,7 @@
|
|||||||
) {
|
) {
|
||||||
console.log('startResearch', query, depth, breadth, feedback)
|
console.log('startResearch', query, depth, breadth, feedback)
|
||||||
tree.value.children = []
|
tree.value.children = []
|
||||||
tree.value.depth = depth
|
selectedNode.value = null
|
||||||
tree.value.breadth = breadth
|
|
||||||
hoveredNode.value = null
|
|
||||||
searchResults.value = {}
|
searchResults.value = {}
|
||||||
try {
|
try {
|
||||||
const combinedQuery = `
|
const combinedQuery = `
|
||||||
@ -178,18 +168,29 @@ ${feedback.map((qa) => `Q: ${qa.assistantQuestion}\nA: ${qa.userAnswer}`).join('
|
|||||||
</template>
|
</template>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="overflow-y-auto">
|
<div class="overflow-y-auto">
|
||||||
<Tree :node="tree" @select="hoveredNode = $event" />
|
<Tree :node="tree" :selected-node="selectedNode" @select="selectedNode = $event" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="hoveredNode" class="p-4">
|
<div v-if="selectedNode" class="p-4">
|
||||||
<h2 class="text-xl font-bold">{{ hoveredNode.label }}</h2>
|
<h2 class="text-xl font-bold">{{ selectedNode.label }}</h2>
|
||||||
<h3 class="text-lg font-semibold mt-2">Research Goal:</h3>
|
|
||||||
<p>{{ hoveredNode.researchGoal }}</p>
|
<!-- Root node has no additional information -->
|
||||||
<div v-if="hoveredNode.learnings">
|
<p v-if="selectedNode.id === '0'"> This is the beginning of your deep research journey! </p>
|
||||||
<h3 class="text-lg font-semibold mt-2">Learnings:</h3>
|
<template v-else>
|
||||||
<ul>
|
<h3 class="text-lg font-semibold mt-2">Research Goal:</h3>
|
||||||
<li v-for="(learning, index) in hoveredNode.learnings" :key="index">{{ learning }}</li>
|
<p>{{ selectedNode.researchGoal }}</p>
|
||||||
|
|
||||||
|
<h3 class="text-lg font-semibold mt-2">Visited URLs:</h3>
|
||||||
|
<ul class="list-disc list-inside">
|
||||||
|
<li v-for="(url, index) in selectedNode.visitedUrls" :key="index">
|
||||||
|
<ULink :href="url" target="_blank">{{ url }}</ULink>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
|
||||||
|
<h3 class="text-lg font-semibold mt-2">Learnings:</h3>
|
||||||
|
<ul class="list-disc list-inside">
|
||||||
|
<li v-for="(learning, index) in selectedNode.learnings" :key="index">{{ learning }}</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</UCard>
|
</UCard>
|
||||||
|
@ -10,18 +10,14 @@
|
|||||||
researchGoal?: string
|
researchGoal?: string
|
||||||
learnings?: string[]
|
learnings?: string[]
|
||||||
followUpQuestions?: string[]
|
followUpQuestions?: string[]
|
||||||
|
visitedUrls?: string[]
|
||||||
status?: TreeNodeStatus
|
status?: TreeNodeStatus
|
||||||
children: TreeNode[]
|
children: TreeNode[]
|
||||||
/** Current depth of the node */
|
|
||||||
depth: number
|
|
||||||
/** Maximum breadth at the current depth */
|
|
||||||
breadth: number
|
|
||||||
/** Index of the node among its siblings */
|
|
||||||
index?: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
node: TreeNode
|
node: TreeNode
|
||||||
|
selectedNode: TreeNode | null
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@ -64,12 +60,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<UIcon name="i-lucide-circle-dot" />
|
<UIcon name="i-lucide-circle-dot" />
|
||||||
<UButton :class="icon.pulse && 'animate-pulse'" :icon="icon.name" size="sm" color="info" @click="emit('select', node)">{{
|
<UButton
|
||||||
node.label
|
:class="icon.pulse && 'animate-pulse'"
|
||||||
}}</UButton>
|
:icon="icon.name"
|
||||||
|
size="sm"
|
||||||
|
:color="selectedNode?.id === node.id ? 'primary' : 'info'"
|
||||||
|
:variant="selectedNode?.id === node.id ? 'soft' : 'outline'"
|
||||||
|
@click="emit('select', node)"
|
||||||
|
>
|
||||||
|
{{ node.label }}
|
||||||
|
</UButton>
|
||||||
<ol v-if="node.children.length > 0" class="space-y-2">
|
<ol v-if="node.children.length > 0" class="space-y-2">
|
||||||
<li v-for="node in node.children" :key="node.id">
|
<li v-for="node in node.children" :key="node.id">
|
||||||
<Tree class="ml-2" :node="node" @select="emit('select', $event)" />
|
<Tree class="ml-2" :node="node" :selected-node @select="emit('select', $event)" />
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,13 +16,13 @@ export type SearchResult = z.infer<typeof searchResultTypeSchema>;
|
|||||||
export type PartialSearchResult = DeepPartial<SearchResult>;
|
export type PartialSearchResult = DeepPartial<SearchResult>;
|
||||||
|
|
||||||
export type ResearchStep =
|
export type ResearchStep =
|
||||||
| { type: 'generating_query'; result: PartialSearchQuery; depth: number; breadth: number; nodeIndex: number; nodeId: string }
|
| { type: 'generating_query'; result: PartialSearchQuery; nodeId: string }
|
||||||
| { type: 'generated_query'; query: string; result: PartialSearchQuery; depth: number; breadth: number; nodeIndex: number; nodeId: string }
|
| { type: 'generated_query'; query: string; result: PartialSearchQuery; nodeId: string }
|
||||||
| { type: 'searching'; query: string; depth: number; breadth: number; nodeIndex: number; nodeId: string }
|
| { type: 'searching'; query: string; nodeId: string }
|
||||||
| { type: 'search_complete'; query: string; urls: string[]; depth: number; breadth: number; nodeIndex: number; nodeId: string }
|
| { type: 'search_complete'; urls: string[]; nodeId: string }
|
||||||
| { type: 'processing_serach_result'; query: string; result: PartialSearchResult; depth: number; breadth: number; nodeIndex: number; nodeId: string }
|
| { type: 'processing_serach_result'; query: string; result: PartialSearchResult; nodeId: string }
|
||||||
| { type: 'processed_search_result'; query: string; result: SearchResult; depth: number; breadth: number; nodeIndex: number; nodeId: string }
|
| { type: 'processed_search_result'; query: string; result: SearchResult; nodeId: string }
|
||||||
| { type: 'error'; message: string; depth: number; nodeId: string }
|
| { type: 'error'; message: string; nodeId: string }
|
||||||
| { type: 'complete' };
|
| { type: 'complete' };
|
||||||
|
|
||||||
// increase this if you have higher API rate limits
|
// increase this if you have higher API rate limits
|
||||||
@ -104,7 +104,6 @@ function processSearchResult({
|
|||||||
numFollowUpQuestions = 3,
|
numFollowUpQuestions = 3,
|
||||||
}: {
|
}: {
|
||||||
query: string;
|
query: string;
|
||||||
// result: SearchResponse;
|
|
||||||
result: TavilySearchResponse
|
result: TavilySearchResponse
|
||||||
numLearnings?: number;
|
numLearnings?: number;
|
||||||
numFollowUpQuestions?: number;
|
numFollowUpQuestions?: number;
|
||||||
@ -214,9 +213,6 @@ export async function deepResearch({
|
|||||||
onProgress({
|
onProgress({
|
||||||
type: 'generating_query',
|
type: 'generating_query',
|
||||||
result: searchQueries[i],
|
result: searchQueries[i],
|
||||||
depth: currentDepth,
|
|
||||||
breadth,
|
|
||||||
nodeIndex: i,
|
|
||||||
nodeId: childNodeId(nodeId, i)
|
nodeId: childNodeId(nodeId, i)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -229,24 +225,18 @@ export async function deepResearch({
|
|||||||
type: 'generated_query',
|
type: 'generated_query',
|
||||||
query,
|
query,
|
||||||
result: searchQueries[i],
|
result: searchQueries[i],
|
||||||
depth: currentDepth,
|
|
||||||
breadth,
|
|
||||||
nodeIndex: i,
|
|
||||||
nodeId: childNodeId(nodeId, i)
|
nodeId: childNodeId(nodeId, i)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
searchQueries.map((searchQuery, nodeIndex) =>
|
searchQueries.map((searchQuery, i) =>
|
||||||
limit(async () => {
|
limit(async () => {
|
||||||
if (!searchQuery?.query) return
|
if (!searchQuery?.query) return
|
||||||
onProgress({
|
onProgress({
|
||||||
type: 'searching',
|
type: 'searching',
|
||||||
query: searchQuery.query,
|
query: searchQuery.query,
|
||||||
depth: currentDepth,
|
nodeId: childNodeId(nodeId, i)
|
||||||
breadth,
|
|
||||||
nodeIndex,
|
|
||||||
nodeId: childNodeId(nodeId, nodeIndex)
|
|
||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
// const result = await firecrawl.search(searchQuery.query, {
|
// const result = await firecrawl.search(searchQuery.query, {
|
||||||
@ -261,6 +251,11 @@ export async function deepResearch({
|
|||||||
|
|
||||||
// Collect URLs from this search
|
// Collect URLs from this search
|
||||||
const newUrls = compact(result.results.map(item => item.url));
|
const newUrls = compact(result.results.map(item => item.url));
|
||||||
|
onProgress({
|
||||||
|
type: 'search_complete',
|
||||||
|
urls: newUrls,
|
||||||
|
nodeId: childNodeId(nodeId, i),
|
||||||
|
})
|
||||||
// Breadth for the next search is half of the current breadth
|
// Breadth for the next search is half of the current breadth
|
||||||
const nextBreadth = Math.ceil(breadth / 2);
|
const nextBreadth = Math.ceil(breadth / 2);
|
||||||
|
|
||||||
@ -280,11 +275,8 @@ export async function deepResearch({
|
|||||||
onProgress({
|
onProgress({
|
||||||
type: 'processing_serach_result',
|
type: 'processing_serach_result',
|
||||||
result: parsedLearnings,
|
result: parsedLearnings,
|
||||||
depth: currentDepth,
|
|
||||||
breadth: breadth,
|
|
||||||
query: searchQuery.query,
|
query: searchQuery.query,
|
||||||
nodeIndex: nodeIndex,
|
nodeId: childNodeId(nodeId, i)
|
||||||
nodeId: childNodeId(nodeId, nodeIndex)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.log(`Processed search result for ${searchQuery.query}`, searchResult);
|
console.log(`Processed search result for ${searchQuery.query}`, searchResult);
|
||||||
@ -298,11 +290,8 @@ export async function deepResearch({
|
|||||||
learnings: allLearnings,
|
learnings: allLearnings,
|
||||||
followUpQuestions: searchResult.followUpQuestions ?? [],
|
followUpQuestions: searchResult.followUpQuestions ?? [],
|
||||||
},
|
},
|
||||||
depth: currentDepth,
|
|
||||||
breadth,
|
|
||||||
query: searchQuery.query,
|
query: searchQuery.query,
|
||||||
nodeIndex: nodeIndex,
|
nodeId: childNodeId(nodeId, i)
|
||||||
nodeId: childNodeId(nodeId, nodeIndex)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (nextDepth < maxDepth && searchResult.followUpQuestions?.length) {
|
if (nextDepth < maxDepth && searchResult.followUpQuestions?.length) {
|
||||||
@ -323,7 +312,7 @@ export async function deepResearch({
|
|||||||
visitedUrls: allUrls,
|
visitedUrls: allUrls,
|
||||||
onProgress,
|
onProgress,
|
||||||
currentDepth: nextDepth,
|
currentDepth: nextDepth,
|
||||||
nodeId: childNodeId(nodeId, nodeIndex),
|
nodeId: childNodeId(nodeId, i),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
@ -342,7 +331,6 @@ export async function deepResearch({
|
|||||||
onProgress({
|
onProgress({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: error?.message ?? 'Something went wrong',
|
message: error?.message ?? 'Something went wrong',
|
||||||
depth: currentDepth,
|
|
||||||
nodeId,
|
nodeId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user