-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat: add web search references feature with sidebar and extraction logic #4515
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey - 我发现了 3 个问题,并给出了一些高层次的反馈:
MessageList.vue中的extractWebSearchResults方法在每次updated钩子时都会运行,每次都会遍历并 JSON 解析整个messages树;建议在每条消息上做结果缓存,或者在messages变更时(例如通过watcher)做 diff,从而避免在每次渲染时都完整重新计算。- 在
MessageList.vue中,provide()暴露的是isDark: this.isDark,这不会对主题变更做出响应;如果isDark在运行时可能变化,并且需要更新RefNode之类的子组件,请提供一个 getter/computed,或者使用toRef/toRefs,以保证注入的使用方能够保持同步。 chat.py中新加的_extract_web_search_refshelper 依赖re,但在这个 diff 中没有看到相应的导入;请确认该模块中存在import re,以避免运行时出现NameError。
给 AI 代理的提示
请根据以下代码审查意见进行修改:
## 整体评论
- `MessageList.vue` 中的 `extractWebSearchResults` 方法在每次 `updated` 钩子时都会运行,每次都会遍历并 JSON 解析整个 `messages` 树;建议在每条消息上做结果缓存,或者在 `messages` 变更时(例如通过 `watcher`)做 diff,从而避免在每次渲染时都完整重新计算。
- 在 `MessageList.vue` 中,`provide()` 暴露的是 `isDark: this.isDark`,这不会对主题变更做出响应;如果 `isDark` 在运行时可能变化,并且需要更新 `RefNode` 之类的子组件,请提供一个 getter/computed,或者使用 `toRef`/`toRefs`,以保证注入的使用方能够保持同步。
- `chat.py` 中新加的 `_extract_web_search_refs` helper 依赖 `re`,但在这个 diff 中没有看到相应的导入;请确认该模块中存在 `import re`,以避免运行时出现 `NameError`。
## 逐条评论
### 评论 1
<location> `dashboard/src/components/chat/message_list_comps/RefNode.vue:22-25` </location>
<code_context>
+ }
+})
+
+console.log('RefNode node:', props.node);
+
+// 从父组件注入的暗黑模式状态和搜索结果
</code_context>
<issue_to_address>
**suggestion:** 请从生产环境组件中移除调试用的 `console.log`。
该日志会在 ref 节点的每次渲染时输出,导致浏览器控制台被大量日志淹没。请将其移除,或用一个调试开关包裹,使其在生产环境中不会执行。
```suggestion
/*
// Debug log for development; uncomment if you need to inspect RefNode props
// console.log('RefNode node:', props.node);
*/
// 从父组件注入的暗黑模式状态和搜索结果
const isDark = inject('isDark', false)
```
</issue_to_address>
### 评论 2
<location> `dashboard/src/components/chat/MessageList.vue:378-383` </location>
<code_context>
+
+ try {
+ // 解析工具调用结果
+ console.log('Parsing web search result:', toolCall.result);
+ const resultData = typeof toolCall.result === 'string'
+ ? JSON.parse(toolCall.result)
</code_context>
<issue_to_address>
**suggestion (performance):** 避免在消息渲染的热点路径中使用过于冗长的 `console.log`。
由于这段代码会在 `mounted` 以及每次 `updated` 时,对所有消息和 tool 调用执行,因此该日志会被非常频繁地触发,可能导致控制台被刷屏,影响页面响应速度和日志可用性。请将其移除,或用一个调试开关进行保护。
```suggestion
try {
// 解析工具调用结果
const resultData = typeof toolCall.result === 'string'
? JSON.parse(toolCall.result)
: toolCall.result;
```
</issue_to_address>
### 评论 3
<location> `dashboard/src/components/chat/MessageList.vue:347` </location>
<code_context>
this.addScrollListener();
this.scrollToBottom();
this.startElapsedTimeTimer();
+ this.extractWebSearchResults();
},
updated() {
</code_context>
<issue_to_address>
**suggestion (performance):** 在每次更新时重新计算网页搜索结果可能比实际需要的开销更大。
`extractWebSearchResults()` 会在每次响应式更新时运行,即使消息和工具调用并没有发生变化,也会遍历所有消息和工具调用。为避免重复工作,可以考虑只在 `messages` 发生变化时触发(例如通过对 `messages` 使用 `watch`),或者按消息 ID 缓存结果。
建议的实现方式:
```
async mounted() {
this.addScrollListener();
this.scrollToBottom();
this.startElapsedTimeTimer();
},
```
```
updated() {
this.initCodeCopyButtons();
if (this.isUserNearBottom) {
this.scrollToBottom();
}
},
watch: {
// Recompute web search results only when messages change
messages: {
handler() {
this.extractWebSearchResults();
},
deep: true,
immediate: true
}
},
methods: {
```
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的代码审查。
Original comment in English
Hey - I've found 3 issues, and left some high level feedback:
- The
extractWebSearchResultsmethod inMessageList.vueruns on everyupdatedhook and walks/JSON-parses the entiremessagestree each time; consider caching per-message results or diffing onmessageschanges (e.g., via a watcher) to avoid repeated full recomputation on every render. - In
MessageList.vue,provide()exposesisDark: this.isDark, which will not react to theme changes; ifisDarkcan change at runtime and should update child components likeRefNode, provide a getter/computed or usetoRef/toRefsso injected consumers stay in sync. - The new
_extract_web_search_refshelper inchat.pyrelies onrebut the import is not shown in this diff; please ensureimport reexists in that module to avoid a runtimeNameError.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `extractWebSearchResults` method in `MessageList.vue` runs on every `updated` hook and walks/JSON-parses the entire `messages` tree each time; consider caching per-message results or diffing on `messages` changes (e.g., via a watcher) to avoid repeated full recomputation on every render.
- In `MessageList.vue`, `provide()` exposes `isDark: this.isDark`, which will not react to theme changes; if `isDark` can change at runtime and should update child components like `RefNode`, provide a getter/computed or use `toRef`/`toRefs` so injected consumers stay in sync.
- The new `_extract_web_search_refs` helper in `chat.py` relies on `re` but the import is not shown in this diff; please ensure `import re` exists in that module to avoid a runtime `NameError`.
## Individual Comments
### Comment 1
<location> `dashboard/src/components/chat/message_list_comps/RefNode.vue:22-25` </location>
<code_context>
+ }
+})
+
+console.log('RefNode node:', props.node);
+
+// 从父组件注入的暗黑模式状态和搜索结果
</code_context>
<issue_to_address>
**suggestion:** Remove debug `console.log` from production component.
This will log on every render of the ref node and clutter the browser console. Please remove it or wrap it in a debug flag so it doesn’t run in production.
```suggestion
/*
// Debug log for development; uncomment if you need to inspect RefNode props
// console.log('RefNode node:', props.node);
*/
// 从父组件注入的暗黑模式状态和搜索结果
const isDark = inject('isDark', false)
```
</issue_to_address>
### Comment 2
<location> `dashboard/src/components/chat/MessageList.vue:378-383` </location>
<code_context>
+
+ try {
+ // 解析工具调用结果
+ console.log('Parsing web search result:', toolCall.result);
+ const resultData = typeof toolCall.result === 'string'
+ ? JSON.parse(toolCall.result)
</code_context>
<issue_to_address>
**suggestion (performance):** Avoid verbose `console.log` in the hot path of message rendering.
Because this runs on `mounted` and every `updated` over all messages and tool calls, this log will be called very frequently and can flood the console, hurting responsiveness and log usability. Please remove it or guard it behind a debug flag.
```suggestion
try {
// 解析工具调用结果
const resultData = typeof toolCall.result === 'string'
? JSON.parse(toolCall.result)
: toolCall.result;
```
</issue_to_address>
### Comment 3
<location> `dashboard/src/components/chat/MessageList.vue:347` </location>
<code_context>
this.addScrollListener();
this.scrollToBottom();
this.startElapsedTimeTimer();
+ this.extractWebSearchResults();
},
updated() {
</code_context>
<issue_to_address>
**suggestion (performance):** Recomputing web search results on every update may be heavier than necessary.
`extractWebSearchResults()` runs on every reactive update, traversing all messages and tool calls even when they haven’t changed. To avoid this repeated work, consider triggering it only when `messages` change (e.g. via a `watch` on `messages`) or caching results by message id.
Suggested implementation:
```
async mounted() {
this.addScrollListener();
this.scrollToBottom();
this.startElapsedTimeTimer();
},
```
```
updated() {
this.initCodeCopyButtons();
if (this.isUserNearBottom) {
this.scrollToBottom();
}
},
watch: {
// Recompute web search results only when messages change
messages: {
handler() {
this.extractWebSearchResults();
},
deep: true,
immediate: true
}
},
methods: {
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| console.log('RefNode node:', props.node); | ||
| // 从父组件注入的暗黑模式状态和搜索结果 | ||
| const isDark = inject('isDark', false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: 请从生产环境组件中移除调试用的 console.log。
该日志会在 ref 节点的每次渲染时输出,导致浏览器控制台被大量日志淹没。请将其移除,或用一个调试开关包裹,使其在生产环境中不会执行。
| console.log('RefNode node:', props.node); | |
| // 从父组件注入的暗黑模式状态和搜索结果 | |
| const isDark = inject('isDark', false) | |
| /* | |
| // Debug log for development; uncomment if you need to inspect RefNode props | |
| // console.log('RefNode node:', props.node); | |
| */ | |
| // 从父组件注入的暗黑模式状态和搜索结果 | |
| const isDark = inject('isDark', false) |
Original comment in English
suggestion: Remove debug console.log from production component.
This will log on every render of the ref node and clutter the browser console. Please remove it or wrap it in a debug flag so it doesn’t run in production.
| console.log('RefNode node:', props.node); | |
| // 从父组件注入的暗黑模式状态和搜索结果 | |
| const isDark = inject('isDark', false) | |
| /* | |
| // Debug log for development; uncomment if you need to inspect RefNode props | |
| // console.log('RefNode node:', props.node); | |
| */ | |
| // 从父组件注入的暗黑模式状态和搜索结果 | |
| const isDark = inject('isDark', false) |
| try { | ||
| // 解析工具调用结果 | ||
| console.log('Parsing web search result:', toolCall.result); | ||
| const resultData = typeof toolCall.result === 'string' | ||
| ? JSON.parse(toolCall.result) | ||
| : toolCall.result; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (performance): 避免在消息渲染的热点路径中使用过于冗长的 console.log。
由于这段代码会在 mounted 以及每次 updated 时,对所有消息和 tool 调用执行,因此该日志会被非常频繁地触发,可能导致控制台被刷屏,影响页面响应速度和日志可用性。请将其移除,或用一个调试开关进行保护。
| try { | |
| // 解析工具调用结果 | |
| console.log('Parsing web search result:', toolCall.result); | |
| const resultData = typeof toolCall.result === 'string' | |
| ? JSON.parse(toolCall.result) | |
| : toolCall.result; | |
| try { | |
| // 解析工具调用结果 | |
| const resultData = typeof toolCall.result === 'string' | |
| ? JSON.parse(toolCall.result) | |
| : toolCall.result; |
Original comment in English
suggestion (performance): Avoid verbose console.log in the hot path of message rendering.
Because this runs on mounted and every updated over all messages and tool calls, this log will be called very frequently and can flood the console, hurting responsiveness and log usability. Please remove it or guard it behind a debug flag.
| try { | |
| // 解析工具调用结果 | |
| console.log('Parsing web search result:', toolCall.result); | |
| const resultData = typeof toolCall.result === 'string' | |
| ? JSON.parse(toolCall.result) | |
| : toolCall.result; | |
| try { | |
| // 解析工具调用结果 | |
| const resultData = typeof toolCall.result === 'string' | |
| ? JSON.parse(toolCall.result) | |
| : toolCall.result; |
| this.addScrollListener(); | ||
| this.scrollToBottom(); | ||
| this.startElapsedTimeTimer(); | ||
| this.extractWebSearchResults(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (performance): 在每次更新时重新计算网页搜索结果可能比实际需要的开销更大。
extractWebSearchResults() 会在每次响应式更新时运行,即使消息和工具调用并没有发生变化,也会遍历所有消息和工具调用。为避免重复工作,可以考虑只在 messages 发生变化时触发(例如通过对 messages 使用 watch),或者按消息 ID 缓存结果。
建议的实现方式:
async mounted() {
this.addScrollListener();
this.scrollToBottom();
this.startElapsedTimeTimer();
},
updated() {
this.initCodeCopyButtons();
if (this.isUserNearBottom) {
this.scrollToBottom();
}
},
watch: {
// Recompute web search results only when messages change
messages: {
handler() {
this.extractWebSearchResults();
},
deep: true,
immediate: true
}
},
methods: {
Original comment in English
suggestion (performance): Recomputing web search results on every update may be heavier than necessary.
extractWebSearchResults() runs on every reactive update, traversing all messages and tool calls even when they haven’t changed. To avoid this repeated work, consider triggering it only when messages change (e.g. via a watch on messages) or caching results by message id.
Suggested implementation:
async mounted() {
this.addScrollListener();
this.scrollToBottom();
this.startElapsedTimeTimer();
},
updated() {
this.initCodeCopyButtons();
if (this.isUserNearBottom) {
this.scrollToBottom();
}
},
watch: {
// Recompute web search results only when messages change
messages: {
handler() {
this.extractWebSearchResults();
},
deep: true,
immediate: true
}
},
methods: {
Modifications / 改动点
Screenshots or Test Results / 运行截图或测试结果
Checklist / 检查清单
requirements.txt和pyproject.toml文件相应位置。/ I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations inrequirements.txtandpyproject.toml.Summary by Sourcery
实现端到端的网页搜索引用功能,在聊天界面进行可视化展示,并在后端完成引用信息的抽取与存储。
New Features:
<ref>标签,使用专门的引用节点组件,并与网页搜索结果的元数据关联。Enhancements:
web_search_tavily引用元数据,包括将被引用的索引映射到相应的搜索结果详情及其网站图标(favicons)。max_results值的结构化 JSON,并通过系统提示引导 LLM 插入<ref>index</ref>引用标记。Original summary in English
Summary by Sourcery
Implement end-to-end web search citation references with UI visualization in chat and backend extraction/storage.
New Features:
Enhancements: