Skip to content

Commit fc2a63b

Browse files
DaltheCowmarkurtzCopilot
authored
Implement guidellm UI (#169)
This PR actually implements the application logic including the UI/charts and the api setup that retrieves data from the window object. --------- Co-authored-by: Mark Kurtz <mark.j.kurtz@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent e2a4066 commit fc2a63b

File tree

207 files changed

+8384
-1508
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

207 files changed

+8384
-1508
lines changed

.eslintrc.json

Lines changed: 0 additions & 69 deletions
This file was deleted.

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ src/ui/next-env.d.ts
223223
# Root-level UI config files that should be tracked
224224
!package.json
225225
!package-lock.json
226-
!.eslintrc.json
227226
!tsconfig.json
228227
!tsconfig.*.json
229228
!src/ui/lib
230229
!src/ui/public/manifest.json
230+
.eslintcache

.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
npx lint-staged

.prettierignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
!tests/ui/**/*.json
1313

1414
# Root-level configs to format
15-
!/.eslintrc.json
15+
!/.eslint.config.js
1616
!/tsconfig*.json
1717
!/*.config.{js,ts}
1818
!/jest.setup.ts

DEVELOPING.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,13 @@ The GuideLLM project includes a frontend UI located in `src/ui`, built using [Ne
185185

186186
### Getting Started
187187

188-
To start the local development server:
188+
First, install dependencies:
189+
190+
```bash
191+
npm install
192+
```
193+
194+
Then, start the local development server:
189195

190196
```bash
191197
npm run dev
@@ -215,6 +221,12 @@ npm run build
215221
npm run test:integration
216222
```
217223

224+
- **Integration+Unit tests with coverage**:
225+
226+
```bash
227+
npm run coverage
228+
```
229+
218230
- **End-to-end tests** (using Cypress, ensure live dev server):
219231

220232
```bash
@@ -241,6 +253,20 @@ npm run build
241253
npm run type-checks
242254
```
243255

256+
##### Tagging Tests
257+
258+
Reference [https://www.npmjs.com/package/jest-runner-groups](jest-runner-groups) Add @group with the tag in a docblock at the top of the test file to indicate which types of tests are contained within. Can't distinguish between different types of tests in the same file.
259+
260+
```
261+
/**
262+
* Admin dashboard tests
263+
*
264+
* @group smoke
265+
* @group sanity
266+
* @group regression
267+
*/
268+
```
269+
244270
## Additional Resources
245271

246272
- [CONTRIBUTING.md](https://github.com/neuralmagic/guidellm/blob/main/CONTRIBUTING.md): Guidelines for contributing to the project.

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,48 @@ The `guidellm benchmark` command is used to run benchmarks against a generative
153153

154154
- `--output-path`: Defines the path to save the benchmark results. Supports JSON, YAML, or CSV formats. If a directory is provided, the results will be saved as `benchmarks.json` in that directory. If not set, the results will be saved in the current working directory.
155155

156+
### GuideLLM UI
157+
158+
GuideLLM UI is a companion frontend for visualizing the results of a GuideLLM benchmark run.
159+
160+
### 🛠 Running the UI
161+
162+
1. Use the Hosted Build (Recommended for Most Users)
163+
164+
After running a benchmark with GuideLLM, a report.html file will be generated (by default at guidellm_report/report.html). This file references the latest stable version of the UI hosted at:
165+
166+
```
167+
https://neuralmagic.github.io/guidellm/ui/dev/
168+
```
169+
170+
Open the file in your browser and you're done—no setup required.
171+
172+
2. Build and Serve the UI Locally (For Development) This option is useful if:
173+
174+
- You are actively developing the UI
175+
176+
- You want to test changes to the UI before publishing
177+
178+
- You want full control over how the report is displayed
179+
180+
```bash
181+
npm install
182+
npm run build
183+
npx serve out
184+
```
185+
186+
This will start a local server (e.g., at http://localhost:3000). Then, in your GuideLLM config or CLI flags, point to this local server as the asset base for report generation.
187+
188+
### 🧪 Development Notes
189+
190+
During UI development, it can be helpful to view sample data. We include a sample benchmark run wired into the Redux store under:
191+
192+
```
193+
src/lib/store/[runInfo/workloadDetails/benchmarks]WindowData.ts
194+
```
195+
196+
In the future this will be replaced by a configurable untracked file for dev use.
197+
156198
## Resources
157199

158200
### Documentation

cypress.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ export default defineConfig({
44
e2e: {
55
specPattern: 'tests/ui/cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
66
supportFile: 'tests/ui/cypress/support/e2e.ts',
7-
baseUrl: 'http://localhost:3000', // optional, but good practice
7+
baseUrl: 'http://localhost:3000', // optional
88
},
99
});

eslint.config.js

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
// @ts-check
2+
3+
import eslint from '@eslint/js';
4+
import typescriptPlugin from '@typescript-eslint/eslint-plugin';
5+
import typescriptParser from '@typescript-eslint/parser';
6+
import { FlatCompat } from '@eslint/eslintrc';
7+
import reactPlugin from 'eslint-plugin-react';
8+
import hooksPlugin from 'eslint-plugin-react-hooks';
9+
import importPlugin from 'eslint-plugin-import';
10+
import jestPlugin from 'eslint-plugin-jest';
11+
import noSecretsPlugin from 'eslint-plugin-no-secrets';
12+
import prettierPlugin from 'eslint-plugin-prettier';
13+
import prettierConfig from 'eslint-config-prettier';
14+
import globals from 'globals';
15+
import path from 'node:path';
16+
import { fileURLToPath } from 'node:url';
17+
18+
const __filename = fileURLToPath(import.meta.url);
19+
const __dirname = path.dirname(__filename);
20+
21+
const compat = new FlatCompat({
22+
baseDirectory: __dirname,
23+
recommendedConfig: eslint.configs.recommended,
24+
});
25+
26+
export default [
27+
// Base configuration
28+
eslint.configs.recommended,
29+
30+
// Next.js configuration using FlatCompat
31+
...compat.extends('next/core-web-vitals'),
32+
33+
// --- Main Configuration ---
34+
{
35+
files: ['src/**/*.{js,jsx,ts,tsx}', 'tests/**/*.{js,jsx,ts,tsx}'],
36+
languageOptions: {
37+
parser: typescriptParser,
38+
ecmaVersion: 2024,
39+
sourceType: 'module',
40+
globals: {
41+
...globals.browser,
42+
...globals.node,
43+
...globals.jest,
44+
},
45+
parserOptions: {
46+
ecmaFeatures: {
47+
jsx: true,
48+
},
49+
project: [
50+
'./src/ui/tsconfig.json',
51+
'./tsconfig.test.json',
52+
'./tsconfig.cypress.json',
53+
],
54+
tsconfigRootDir: import.meta.dirname,
55+
noWarnOnMultipleProjects: true,
56+
},
57+
},
58+
plugins: {
59+
'@typescript-eslint': typescriptPlugin,
60+
react: reactPlugin,
61+
'react-hooks': hooksPlugin,
62+
import: importPlugin,
63+
jest: jestPlugin,
64+
'no-secrets': noSecretsPlugin,
65+
prettier: prettierPlugin,
66+
},
67+
rules: {
68+
// Ccustom rules
69+
complexity: ['warn', { max: 8 }],
70+
curly: ['error', 'all'],
71+
'no-unused-vars': 'off',
72+
73+
// TypeScript rules
74+
'@typescript-eslint/no-unused-vars': [
75+
'warn',
76+
{
77+
argsIgnorePattern: '^_',
78+
varsIgnorePattern: '^_',
79+
caughtErrorsIgnorePattern: '^_',
80+
},
81+
],
82+
'@typescript-eslint/no-explicit-any': 'warn',
83+
84+
// Next.js overrides
85+
'@next/next/no-img-element': 'off', // Allow img tags if needed
86+
'@next/next/no-page-custom-font': 'warn',
87+
88+
// React rules
89+
'react/react-in-jsx-scope': 'off', // Not needed in Next.js
90+
'react/prop-types': 'off', // Using TypeScript
91+
'react-hooks/rules-of-hooks': 'error',
92+
'react-hooks/exhaustive-deps': 'warn',
93+
94+
// Import rules
95+
'import/no-extraneous-dependencies': [
96+
'error',
97+
{
98+
devDependencies: [
99+
'**/*.test.{js,jsx,ts,tsx}',
100+
'**/*.d.ts',
101+
'**/*.interfaces.ts',
102+
'**/*.setup.{js,ts}',
103+
'**/*.config.{js,mjs,ts}',
104+
'tests/**/*',
105+
'cypress/**/*',
106+
],
107+
optionalDependencies: false,
108+
peerDependencies: false,
109+
},
110+
],
111+
'import/order': [
112+
'error',
113+
{
114+
groups: [
115+
['builtin', 'external'],
116+
['internal', 'parent', 'sibling', 'index'],
117+
],
118+
'newlines-between': 'always-and-inside-groups',
119+
pathGroups: [
120+
{
121+
pattern:
122+
'@{app,assets,classes,components,hooks,lib,pages,store,tests,types,utils}/**',
123+
group: 'internal',
124+
position: 'before',
125+
},
126+
{
127+
pattern: '{.,..}/**',
128+
group: 'internal',
129+
position: 'after',
130+
},
131+
],
132+
pathGroupsExcludedImportTypes: ['builtin'],
133+
alphabetize: { order: 'asc', caseInsensitive: true },
134+
},
135+
],
136+
137+
// Security
138+
'no-secrets/no-secrets': ['error', { additionalRegexes: {}, ignoreContent: [] }],
139+
140+
// Prettier
141+
'prettier/prettier': 'error',
142+
},
143+
settings: {
144+
next: {
145+
rootDir: ['src/ui/', 'tests/ui/'],
146+
},
147+
'import/resolver': {
148+
typescript: {
149+
project: [
150+
'./src/ui/tsconfig.json',
151+
'./tsconfig.test.json',
152+
'./tsconfig.cypress.json',
153+
],
154+
noWarnOnMultipleProjects: true,
155+
},
156+
},
157+
react: {
158+
version: 'detect',
159+
},
160+
},
161+
},
162+
163+
// Jest-specific rules for test files
164+
{
165+
files: [
166+
'tests/**/*.{js,jsx,ts,tsx}',
167+
'**/*.test.{js,jsx,ts,tsx}',
168+
'**/*.spec.{js,jsx,ts,tsx}',
169+
],
170+
rules: {
171+
'jest/expect-expect': 'error',
172+
'jest/no-focused-tests': 'error',
173+
'jest/no-identical-title': 'error',
174+
'jest/prefer-to-have-length': 'warn',
175+
'jest/valid-expect': 'error',
176+
},
177+
},
178+
179+
// Prettier config (disables conflicting rules)
180+
prettierConfig,
181+
];

jest.config.js renamed to jest.config.cjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ const createJestConfig = nextJest({
66
});
77

88
const customJestConfig = {
9-
collectCoverage: true,
9+
collectCoverage: false,
1010
collectCoverageFrom: ['./src/ui/**/*.{ts,tsx}'],
1111
coverageDirectory: './coverage',
1212
coverageProvider: 'v8',
13-
coverageReporters: ['json', 'text-summary', 'lcov'],
13+
coverageReporters: ['text-summary', 'lcov', 'json-summary'],
1414
moduleFileExtensions: ['ts', 'tsx', 'js'],
1515
moduleNameMapper: {
1616
'^.+\\.(svg)$': '<rootDir>/tests/ui/__mocks__/svg.js',

0 commit comments

Comments
 (0)