Skip to content

[WIP]feat(eval): support evaluation visualization#107

Open
zhijianma wants to merge 11 commits intoagentscope-ai:mainfrom
zhijianma:feat/eval
Open

[WIP]feat(eval): support evaluation visualization#107
zhijianma wants to merge 11 commits intoagentscope-ai:mainfrom
zhijianma:feat/eval

Conversation

@zhijianma
Copy link
Member

Description

[Please describe the background, purpose, changes made, and how to test this PR]

Checklist

Please check the following items before code is ready to be reviewed.

  • Code has been formatted with npm run format command in the root directory
  • Docstrings/comments are in appropriate style (TSDoc/JSDoc for TypeScript/JavaScript, Google style for Python)
  • Related documentation has been updated (e.g. links, examples, etc.)
  • Code is ready for review

@gemini-code-assist
Copy link

Summary of Changes

Hello @zhijianma, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the application's capability to display and analyze evaluation data. It provides users with a rich, interactive interface to import evaluation results, view high-level summaries, dive into specific metrics, and trace the execution paths of individual tasks. The changes span both frontend and backend, establishing a robust foundation for future evaluation-centric features.

Highlights

  • Evaluation Visualization Feature: Introduced a comprehensive suite of features for visualizing evaluation results, including detailed metrics, task-level data, and trajectory analysis.
  • Frontend Architecture Overhaul: Refactored evaluation-related state management with new React Contexts (EvaluationContext, EvaluationListContext, EvaluationTaskContext, EvaluationTasksContext) and introduced new UI components for charting (ECharts) and local file picking.
  • Backend Data Management: Implemented new Data Access Objects (EvaluationDao, FileDao) and a database entity (EvaluationTable) to store evaluation metadata and read detailed evaluation results from the file system. New TRPC procedures and socket events were added to support these operations.
  • Dynamic Metric Visualization: Added components (CategoricalView, NumericalView) to dynamically render different types of metrics (numerical and categorical) with appropriate charts like bar charts, pie charts, and CDF plots.
  • Task Trajectory Analysis: Developed a Sankey diagram visualization (ChartPage) to illustrate the flow and tool usage within individual evaluation task repeats, allowing for detailed inspection of agent trajectories.
Ignored Files
  • Ignored by pattern: .github/workflows/** (2)
    • .github/workflows/format.yml
    • .github/workflows/pre-commit.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new evaluation visualization feature, including new UI components, data models, and API endpoints. The changes are extensive and well-structured, providing a comprehensive view of evaluation results and task details. The use of context providers for managing evaluation and task data is a good architectural choice. There are a few areas where the code could be improved for robustness, consistency, and maintainability.

Comment on lines +601 to +602
// TODO: check if the request is from localhost

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The listDir endpoint has a TODO comment indicating that it should be protected to only allow requests from localhost for security reasons. Exposing local file system access without proper authorization can be a significant security vulnerability. This TODO should be addressed with high priority.

children: item.isDirectory ? [] : undefined,
isLeaf: !item.isDirectory,
icon: item.isDirectory ? <FolderOutlined /> : <FileOutlined />,
selectable: item.isDirectory,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The selectable property is hardcoded to item.isDirectory. This means only directories will be selectable in the tree. However, the Props interface allows type: 'file' | 'directory' | 'both'. If the type prop is 'file' or 'both', this logic would be incorrect. The selectable property should dynamically depend on the type prop to allow selection of files or both files and directories as needed.

Comment on lines +120 to +130
callback({
success: true,
message:
'Directory listed successfully',
data: {
title: fileName,
isDirectory: stats.isDirectory(),
modifiedTime: stats.mtime,
},
} as ResponseBody);
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The callback function is being called inside the map function, which means it will be invoked for each file found in the directory. This is incorrect, as a socket callback should typically be called only once with the complete result. The callback should be called after the map operation, passing the entire fileNames array as data.

Comment on lines +252 to +258
// checked={isChecked(tagRecord.tag, tableRequestParams)}
checked={(
(tableRequestParams
.filters?.tags
?.value as string[]) ||
[]
).includes(tagRecord.tag)}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Checkbox component's checked prop uses a potentially complex expression. The commented-out isChecked function suggests a previous approach. Ensure the current logic for determining checked state is clear, efficient, and correctly handles all edge cases, especially concerning array filtering.

Comment on lines +134 to +136
const formatNumber = (num: number, decimals: number = 6): number => {
return parseFloat(num.toFixed(decimals));
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

A formatNumber function is defined here, but a global formatNumber is also imported from @/utils/common. Having two functions with the same name can lead to confusion and potential inconsistencies. It's best to consolidate into a single utility or rename one to avoid ambiguity.

Comment on lines +807 to +809
} catch (error) {
console.error('Error in getEvaluationTask:', error);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The catch block for getEvaluationTask only logs the error to the console and does not throw a TRPCError. This means the client might not receive proper error feedback. It should throw a TRPCError similar to other endpoints for consistent error handling.

const requiredBenchmarkFields = [
'name',
'description',
// 'total_tasks',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The total_tasks field is commented out in requiredBenchmarkFields. If total_tasks is an optional field, it should be removed from this list. If it is a required field, it should be uncommented to ensure proper validation of the metadata.

Comment on lines +109 to +110
if (fs.existsSync(dirPath)) {
// 获取该目录下所有的文件和文件夹,只获取他们的名字,是否是文件夹,修改时间

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using fs.existsSync and fs.readdirSync for file system operations is synchronous. In a server environment, synchronous I/O can block the event loop, leading to performance issues. It's recommended to use asynchronous fs.promises.stat and fs.promises.readdir for non-blocking operations.

window.removeEventListener('resize', handleResize);
chartInstanceRef.current?.dispose();
};
}, [theme, onChartReady]);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The useEffect hook depends on theme and onChartReady. If onChartReady is not memoized, it will cause this effect to re-run on every render, potentially leading to performance issues. Ensure onChartReady is wrapped in useCallback in the parent component if it's not already.

Comment on lines +587 to +609
socket.on(
SocketEvents.client.getEvaluationResult,
async (
evaluationDir: string,
callback: (res: ResponseBody) => void,
) => {
try {
const data = await FileDao.getJSONFile<EvalResult>(
path.join(evaluationDir, 'evaluation_result.json'),
);
callback({
success: true,
message: 'Get evaluation result successfully',
data: data,
} as ResponseBody);
} catch (error) {
console.error(error);
callback({
success: false,
message: `Error: ${error}`,
} as ResponseBody);
}
},

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This getEvaluationResult socket event is redundant as a tRPC endpoint (getEvaluationData) already exists for fetching evaluation results. It's recommended to consolidate data fetching logic into tRPC procedures for better consistency, type safety, and maintainability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant