mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-29 20:20:57 +00:00
feat: enhance InsightPrompts and components with additional data handling
- Updated InsightPrompts to clarify user request counting guidelines. - Modified App.js to pass new props (topGoals, topTools) to ProjectAreas and ImpressiveWorkflows components. - Enhanced ProjectAreas and ImpressiveWorkflows components to utilize new props for improved data visualization. - Refactored FrictionPoints component layout to use grid display for better responsiveness. - Removed legacy insight-app.js file to streamline the codebase. - Expanded StaticInsightTypes to include primarySuccess, outcomes, and topGoals for better data structure.
This commit is contained in:
parent
4c32f4b646
commit
af21e7fdd9
6 changed files with 155 additions and 1153 deletions
|
|
@ -281,8 +281,14 @@ export class DataProcessor {
|
|||
if (onProgress) onProgress('Generating qualitative insights', 80);
|
||||
const qualitative = await this.generateQualitativeInsights(metrics, facets);
|
||||
|
||||
// Aggregate satisfaction and friction data from facets
|
||||
const { satisfactionAgg, frictionAgg } = this.aggregateFacetsData(facets);
|
||||
// Aggregate satisfaction, friction, success and outcome data from facets
|
||||
const {
|
||||
satisfactionAgg,
|
||||
frictionAgg,
|
||||
primarySuccessAgg,
|
||||
outcomesAgg,
|
||||
goalsAgg,
|
||||
} = this.aggregateFacetsData(facets);
|
||||
|
||||
if (onProgress) onProgress('Finalizing report', 100);
|
||||
|
||||
|
|
@ -291,6 +297,9 @@ export class DataProcessor {
|
|||
qualitative,
|
||||
satisfaction: satisfactionAgg,
|
||||
friction: frictionAgg,
|
||||
primarySuccess: primarySuccessAgg,
|
||||
outcomes: outcomesAgg,
|
||||
topGoals: goalsAgg,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -298,9 +307,15 @@ export class DataProcessor {
|
|||
private aggregateFacetsData(facets: SessionFacets[]): {
|
||||
satisfactionAgg: Record<string, number>;
|
||||
frictionAgg: Record<string, number>;
|
||||
primarySuccessAgg: Record<string, number>;
|
||||
outcomesAgg: Record<string, number>;
|
||||
goalsAgg: Record<string, number>;
|
||||
} {
|
||||
const satisfactionAgg: Record<string, number> = {};
|
||||
const frictionAgg: Record<string, number> = {};
|
||||
const primarySuccessAgg: Record<string, number> = {};
|
||||
const outcomesAgg: Record<string, number> = {};
|
||||
const goalsAgg: Record<string, number> = {};
|
||||
|
||||
facets.forEach((facet) => {
|
||||
// Aggregate satisfaction
|
||||
|
|
@ -312,9 +327,31 @@ export class DataProcessor {
|
|||
Object.entries(facet.friction_counts).forEach(([fric, count]) => {
|
||||
frictionAgg[fric] = (frictionAgg[fric] || 0) + count;
|
||||
});
|
||||
|
||||
// Aggregate primary success
|
||||
if (facet.primary_success && facet.primary_success !== 'none') {
|
||||
primarySuccessAgg[facet.primary_success] =
|
||||
(primarySuccessAgg[facet.primary_success] || 0) + 1;
|
||||
}
|
||||
|
||||
// Aggregate outcomes
|
||||
if (facet.outcome) {
|
||||
outcomesAgg[facet.outcome] = (outcomesAgg[facet.outcome] || 0) + 1;
|
||||
}
|
||||
|
||||
// Aggregate goals
|
||||
Object.entries(facet.goal_categories).forEach(([goal, count]) => {
|
||||
goalsAgg[goal] = (goalsAgg[goal] || 0) + count;
|
||||
});
|
||||
});
|
||||
|
||||
return { satisfactionAgg, frictionAgg };
|
||||
return {
|
||||
satisfactionAgg,
|
||||
frictionAgg,
|
||||
primarySuccessAgg,
|
||||
outcomesAgg,
|
||||
goalsAgg,
|
||||
};
|
||||
}
|
||||
|
||||
private async generateQualitativeInsights(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,15 @@ CRITICAL GUIDELINES:
|
|||
1. **goal_categories**: Count ONLY what the USER explicitly asked for.
|
||||
- DO NOT count Qwen's autonomous codebase exploration
|
||||
- DO NOT count work Qwen decided to do on its own
|
||||
- ONLY count when user says "can you...", "please...", "I need...", "let's..."
|
||||
- ONLY count when user says "can you...", "please...", "I need...", "let's...
|
||||
- POSSIBLE CATEGORIES (but be open to others that appear in the data):
|
||||
- bug_fix
|
||||
- feature_request
|
||||
- debugging
|
||||
- test_creation
|
||||
- code_refactoring
|
||||
- documentation_update
|
||||
"
|
||||
|
||||
2. **user_satisfaction_counts**: Base ONLY on explicit user signals.
|
||||
- "Yay!", "great!", "perfect!" → happy
|
||||
|
|
|
|||
|
|
@ -40,7 +40,11 @@ function InsightApp({ data }) {
|
|||
|
||||
{data.qualitative && (
|
||||
<>
|
||||
<ProjectAreas qualitative={data.qualitative} />
|
||||
<ProjectAreas
|
||||
qualitative={data.qualitative}
|
||||
topGoals={data.topGoals}
|
||||
topTools={data.topTools}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
|
@ -54,7 +58,11 @@ function InsightApp({ data }) {
|
|||
|
||||
{data.qualitative && (
|
||||
<>
|
||||
<ImpressiveWorkflows qualitative={data.qualitative} />
|
||||
<ImpressiveWorkflows
|
||||
qualitative={data.qualitative}
|
||||
primarySuccess={data.primarySuccess}
|
||||
outcomes={data.outcomes}
|
||||
/>
|
||||
<FrictionPoints
|
||||
qualitative={data.qualitative}
|
||||
satisfaction={data.satisfaction}
|
||||
|
|
|
|||
|
|
@ -62,10 +62,13 @@ function NavToc() {
|
|||
);
|
||||
}
|
||||
|
||||
function ProjectAreas({ qualitative }) {
|
||||
function ProjectAreas({ qualitative, topGoals, topTools }) {
|
||||
const { projectAreas } = qualitative;
|
||||
if (!Array.isArray(projectAreas?.areas) || !projectAreas.areas.length)
|
||||
return null;
|
||||
|
||||
// Convert topTools (array of tuples) to object for chart if needed
|
||||
const topToolsObj = Array.isArray(topTools)
|
||||
? Object.fromEntries(topTools)
|
||||
: topTools;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -75,18 +78,47 @@ function ProjectAreas({ qualitative }) {
|
|||
>
|
||||
What You Work On
|
||||
</h2>
|
||||
<div className="project-areas">
|
||||
{projectAreas.areas.map((area, idx) => (
|
||||
<div key={idx} className="project-area">
|
||||
<div className="area-header">
|
||||
<span className="area-name">{area.name}</span>
|
||||
<span className="area-count">~{area.session_count} sessions</span>
|
||||
|
||||
{Array.isArray(projectAreas?.areas) && projectAreas.areas.length > 0 && (
|
||||
<div className="project-areas mb-6">
|
||||
{projectAreas.areas.map((area, idx) => (
|
||||
<div key={idx} className="project-area">
|
||||
<div className="area-header">
|
||||
<span className="area-name">{area.name}</span>
|
||||
<span className="area-count">
|
||||
~{area.session_count} sessions
|
||||
</span>
|
||||
</div>
|
||||
<div className="area-desc">
|
||||
<MarkdownText>{area.description}</MarkdownText>
|
||||
</div>
|
||||
</div>
|
||||
<div className="area-desc">
|
||||
<MarkdownText>{area.description}</MarkdownText>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(2, 1fr)',
|
||||
gap: '24px',
|
||||
marginBottom: '24px',
|
||||
}}
|
||||
>
|
||||
{topGoals && Object.keys(topGoals).length > 0 && (
|
||||
<HorizontalBarChart
|
||||
data={topGoals}
|
||||
title="What You Wanted"
|
||||
color="#0ea5e9"
|
||||
/>
|
||||
)}
|
||||
{topToolsObj && Object.keys(topToolsObj).length > 0 && (
|
||||
<HorizontalBarChart
|
||||
data={topToolsObj}
|
||||
title="Top Tools Used"
|
||||
color="#6366f1"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
@ -119,7 +151,7 @@ function InteractionStyle({ qualitative }) {
|
|||
);
|
||||
}
|
||||
|
||||
function ImpressiveWorkflows({ qualitative }) {
|
||||
function ImpressiveWorkflows({ qualitative, primarySuccess, outcomes }) {
|
||||
const { impressiveWorkflows } = qualitative;
|
||||
if (!impressiveWorkflows) return null;
|
||||
|
||||
|
|
@ -147,12 +179,55 @@ function ImpressiveWorkflows({ qualitative }) {
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(2, 1fr)',
|
||||
gap: '24px',
|
||||
marginTop: '24px',
|
||||
marginBottom: '24px',
|
||||
}}
|
||||
>
|
||||
{primarySuccess && Object.keys(primarySuccess).length > 0 && (
|
||||
<HorizontalBarChart
|
||||
data={primarySuccess}
|
||||
title="What Helped Most (Qwen's Capabilities)"
|
||||
color="#3b82f6"
|
||||
allowedKeys={[
|
||||
'fast_accurate_search',
|
||||
'correct_code_edits',
|
||||
'good_explanations',
|
||||
'proactive_help',
|
||||
'multi_file_changes',
|
||||
'good_debugging',
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
{outcomes && Object.keys(outcomes).length > 0 && (
|
||||
<HorizontalBarChart
|
||||
data={outcomes}
|
||||
title="Outcomes"
|
||||
color="#8b5cf6"
|
||||
allowedKeys={[
|
||||
'fully_achieved',
|
||||
'mostly_achieved',
|
||||
'partially_achieved',
|
||||
'not_achieved',
|
||||
'unclear_from_transcript',
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// Format label for display (capitalize and replace underscores with spaces)
|
||||
function formatLabel(label) {
|
||||
if (label === 'unclear_from_transcript') {
|
||||
return 'Unclear';
|
||||
}
|
||||
return label
|
||||
.split('_')
|
||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
|
|
@ -197,6 +272,7 @@ function HorizontalBarChart({
|
|||
fontSize: '13px',
|
||||
fontWeight: 700,
|
||||
color: '#64748b',
|
||||
marginTop: 0,
|
||||
marginBottom: '16px',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.5px',
|
||||
|
|
@ -324,7 +400,8 @@ function FrictionPoints({ qualitative, satisfaction, friction }) {
|
|||
{/* Facets Data Charts */}
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(2, 1fr)',
|
||||
gap: '24px',
|
||||
marginTop: '24px',
|
||||
marginBottom: '24px',
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -28,6 +28,9 @@ export interface InsightData {
|
|||
qualitative?: QualitativeInsights;
|
||||
satisfaction?: Record<string, number>;
|
||||
friction?: Record<string, number>;
|
||||
primarySuccess?: Record<string, number>;
|
||||
outcomes?: Record<string, number>;
|
||||
topGoals?: Record<string, number>;
|
||||
}
|
||||
|
||||
export interface StreakData {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue