Skip to content

Commit a60460e

Browse files
Feature: implement feedback loop explain process (#528)
* update deploy ai service response structure * add explainBackgroundTracker * set columns in threadResponseExplain table to nullable * add analysis api in ibis adaptor * implement util to add autoIncremented id * feature: feedback loop create explanation job * add explain status for FE to check if the explanation job is requested or not * fix rebase error * feat: Add threadResponseExplainRepository to apollo server context * update migration file * upper case error code * get latest explain, modify base repository orderby parameter * add error code for OLD_VERSION error * fix lint error * update error message in migration file * feat(wren-ui): Integrate thread response explanation API & refine process (#539) * feat(wren-ui): add ExplainTaskStatus enum to schema, add reverseEnum helper, fix transform statusAndError, fix non-nullable reference's summary value * feat(wren-ui): generate createThreadResponseExplain graphQL API * feat(wren-ui): replace references data to API's data * feat(wren-ui): refine explain references flow in UI * feat(wren-ui): refine error showing when get explanation failed * feat(wren-ui): refine the references old version & error retry process * feat(wren-ui): generate references number sequence * feat(wren-ui): show the first reference in step when uncollapse * feat(wren-ui): save correction's reference number to DB * feat(wren-ui): update retrieve error text from BE only * feat(wren-ui): add CreateThreadResponseExplain graphQL API error handler --------- Co-authored-by: Shimin <andreashimin@gmail.com>
1 parent 76d5734 commit a60460e

35 files changed

+1663
-309
lines changed

wren-ui/migrations/20240711021133_create_thread_response_explain_table.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ exports.up = function (knex) {
1313
.references('thread_response.id')
1414
.onDelete('CASCADE');
1515

16-
table.string('query_id').notNullable();
17-
table.string('status').notNullable();
18-
table.jsonb('detail').notNullable();
19-
table.jsonb('error').notNullable();
16+
table.string('query_id').nullable();
17+
table.string('status').nullable();
18+
table.jsonb('detail').nullable();
19+
table.jsonb('error').nullable();
20+
table.jsonb('analysis').nullable();
2021

2122
// timestamps
2223
table.timestamps(true, true);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* @param { import("knex").Knex } knex
3+
* @returns { Promise<void> }
4+
*/
5+
exports.up = async function (knex) {
6+
const threadResponses = await knex('thread_response').select('*');
7+
if (threadResponses.length === 0) {
8+
return;
9+
}
10+
const explainData = threadResponses.map((threadResponse) => {
11+
const error = {
12+
code: 'OLD_VERSION',
13+
message:
14+
'Question asked before v0.8.0. Click "Retry" to generate manually.',
15+
};
16+
return {
17+
thread_response_id: threadResponse.id,
18+
status: 'FAILED',
19+
error: process.env.DB_TYPE === 'pg' ? error : JSON.stringify(error),
20+
};
21+
});
22+
23+
await knex('thread_response_explain').insert(explainData);
24+
};
25+
26+
/**
27+
* @param { import("knex").Knex } knex
28+
* @returns { Promise<void> }
29+
*/
30+
exports.down = async function (knex) {
31+
// remove all data
32+
await knex('thread_response_explain').delete();
33+
};

wren-ui/src/apollo/client/graphql/__types__.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export type CorrectionDetail = {
7575
__typename?: 'CorrectionDetail';
7676
correction: Scalars['String'];
7777
id: Scalars['Int'];
78+
referenceNum: Scalars['Int'];
7879
type: ReferenceType;
7980
};
8081

@@ -120,10 +121,15 @@ export type CreateThreadResponseCorrectionInput = {
120121
correction: Scalars['String'];
121122
id: Scalars['Int'];
122123
reference: Scalars['String'];
124+
referenceNum: Scalars['Int'];
123125
stepIndex: Scalars['Int'];
124126
type: ReferenceType;
125127
};
126128

129+
export type CreateThreadResponseExplainWhereInput = {
130+
responseId: Scalars['Int'];
131+
};
132+
127133
export type CreateThreadResponseInput = {
128134
question?: InputMaybe<Scalars['String']>;
129135
sql?: InputMaybe<Scalars['String']>;
@@ -162,9 +168,19 @@ export enum DataSourceName {
162168
POSTGRES = 'POSTGRES'
163169
}
164170

171+
export type DetailReference = {
172+
__typename?: 'DetailReference';
173+
referenceId?: Maybe<Scalars['Int']>;
174+
sqlLocation?: Maybe<ReferenceSqlLocation>;
175+
sqlSnippet?: Maybe<Scalars['String']>;
176+
summary: Scalars['String'];
177+
type: ReferenceType;
178+
};
179+
165180
export type DetailStep = {
166181
__typename?: 'DetailStep';
167182
cteName?: Maybe<Scalars['String']>;
183+
references?: Maybe<Array<Maybe<DetailReference>>>;
168184
sql: Scalars['String'];
169185
summary: Scalars['String'];
170186
};
@@ -344,6 +360,13 @@ export type Error = {
344360
stacktrace?: Maybe<Array<Maybe<Scalars['String']>>>;
345361
};
346362

363+
export enum ExplainTaskStatus {
364+
FAILED = 'FAILED',
365+
FINISHED = 'FINISHED',
366+
GENERATING = 'GENERATING',
367+
UNDERSTANDING = 'UNDERSTANDING'
368+
}
369+
347370
export enum ExpressionName {
348371
ABS = 'ABS',
349372
AVG = 'AVG',
@@ -424,6 +447,7 @@ export type Mutation = {
424447
createRelation: Scalars['JSON'];
425448
createThread: Thread;
426449
createThreadResponse: ThreadResponse;
450+
createThreadResponseExplain: Scalars['JSON'];
427451
createView: ViewInfo;
428452
deleteCalculatedField: Scalars['Boolean'];
429453
deleteModel: Scalars['Boolean'];
@@ -496,6 +520,11 @@ export type MutationCreateThreadResponseArgs = {
496520
};
497521

498522

523+
export type MutationCreateThreadResponseExplainArgs = {
524+
where: CreateThreadResponseExplainWhereInput;
525+
};
526+
527+
499528
export type MutationCreateViewArgs = {
500529
data: CreateViewInput;
501530
};
@@ -731,6 +760,12 @@ export type RecommendRelations = {
731760
relations: Array<Maybe<Relation>>;
732761
};
733762

763+
export type ReferenceSqlLocation = {
764+
__typename?: 'ReferenceSQLLocation';
765+
column: Scalars['Int'];
766+
line: Scalars['Int'];
767+
};
768+
734769
export enum ReferenceType {
735770
FIELD = 'FIELD',
736771
FILTER = 'FILTER',
@@ -865,6 +900,7 @@ export type ThreadResponse = {
865900
corrections?: Maybe<Array<CorrectionDetail>>;
866901
detail?: Maybe<ThreadResponseDetail>;
867902
error?: Maybe<Error>;
903+
explain?: Maybe<ThreadResponseExplainInfo>;
868904
id: Scalars['Int'];
869905
question: Scalars['String'];
870906
status: AskingTaskStatus;
@@ -879,6 +915,13 @@ export type ThreadResponseDetail = {
879915
view?: Maybe<ViewInfo>;
880916
};
881917

918+
export type ThreadResponseExplainInfo = {
919+
__typename?: 'ThreadResponseExplainInfo';
920+
error?: Maybe<Scalars['JSON']>;
921+
queryId?: Maybe<Scalars['String']>;
922+
status?: Maybe<ExplainTaskStatus>;
923+
};
924+
882925
export type ThreadUniqueWhereInput = {
883926
id: Scalars['Int'];
884927
};

wren-ui/src/apollo/client/graphql/home.generated.ts

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import * as Apollo from '@apollo/client';
55
const defaultOptions = {} as const;
66
export type CommonErrorFragment = { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null };
77

8-
export type CommonResponseFragment = { __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null, corrections?: Array<{ __typename?: 'CorrectionDetail', id: number, type: Types.ReferenceType, correction: string }> | null };
8+
export type CommonResponseFragment = { __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null, references?: Array<{ __typename?: 'DetailReference', referenceId?: number | null, summary: string, type: Types.ReferenceType, sqlSnippet?: string | null, sqlLocation?: { __typename?: 'ReferenceSQLLocation', column: number, line: number } | null } | null> | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null, explain?: { __typename?: 'ThreadResponseExplainInfo', queryId?: string | null, status?: Types.ExplainTaskStatus | null, error?: any | null } | null, corrections?: Array<{ __typename?: 'CorrectionDetail', id: number, type: Types.ReferenceType, referenceNum: number, correction: string }> | null };
99

1010
export type SuggestedQuestionsQueryVariables = Types.Exact<{ [key: string]: never; }>;
1111

@@ -29,14 +29,14 @@ export type ThreadQueryVariables = Types.Exact<{
2929
}>;
3030

3131

32-
export type ThreadQuery = { __typename?: 'Query', thread: { __typename?: 'DetailedThread', id: number, sql: string, summary: string, responses: Array<{ __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null, corrections?: Array<{ __typename?: 'CorrectionDetail', id: number, type: Types.ReferenceType, correction: string }> | null }> } };
32+
export type ThreadQuery = { __typename?: 'Query', thread: { __typename?: 'DetailedThread', id: number, sql: string, summary: string, responses: Array<{ __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null, references?: Array<{ __typename?: 'DetailReference', referenceId?: number | null, summary: string, type: Types.ReferenceType, sqlSnippet?: string | null, sqlLocation?: { __typename?: 'ReferenceSQLLocation', column: number, line: number } | null } | null> | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null, explain?: { __typename?: 'ThreadResponseExplainInfo', queryId?: string | null, status?: Types.ExplainTaskStatus | null, error?: any | null } | null, corrections?: Array<{ __typename?: 'CorrectionDetail', id: number, type: Types.ReferenceType, referenceNum: number, correction: string }> | null }> } };
3333

3434
export type ThreadResponseQueryVariables = Types.Exact<{
3535
responseId: Types.Scalars['Int'];
3636
}>;
3737

3838

39-
export type ThreadResponseQuery = { __typename?: 'Query', threadResponse: { __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null, corrections?: Array<{ __typename?: 'CorrectionDetail', id: number, type: Types.ReferenceType, correction: string }> | null } };
39+
export type ThreadResponseQuery = { __typename?: 'Query', threadResponse: { __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null, references?: Array<{ __typename?: 'DetailReference', referenceId?: number | null, summary: string, type: Types.ReferenceType, sqlSnippet?: string | null, sqlLocation?: { __typename?: 'ReferenceSQLLocation', column: number, line: number } | null } | null> | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null, explain?: { __typename?: 'ThreadResponseExplainInfo', queryId?: string | null, status?: Types.ExplainTaskStatus | null, error?: any | null } | null, corrections?: Array<{ __typename?: 'CorrectionDetail', id: number, type: Types.ReferenceType, referenceNum: number, correction: string }> | null } };
4040

4141
export type CreateAskingTaskMutationVariables = Types.Exact<{
4242
data: Types.AskingTaskInput;
@@ -65,7 +65,14 @@ export type CreateThreadResponseMutationVariables = Types.Exact<{
6565
}>;
6666

6767

68-
export type CreateThreadResponseMutation = { __typename?: 'Mutation', createThreadResponse: { __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null, corrections?: Array<{ __typename?: 'CorrectionDetail', id: number, type: Types.ReferenceType, correction: string }> | null } };
68+
export type CreateThreadResponseMutation = { __typename?: 'Mutation', createThreadResponse: { __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null, references?: Array<{ __typename?: 'DetailReference', referenceId?: number | null, summary: string, type: Types.ReferenceType, sqlSnippet?: string | null, sqlLocation?: { __typename?: 'ReferenceSQLLocation', column: number, line: number } | null } | null> | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null, explain?: { __typename?: 'ThreadResponseExplainInfo', queryId?: string | null, status?: Types.ExplainTaskStatus | null, error?: any | null } | null, corrections?: Array<{ __typename?: 'CorrectionDetail', id: number, type: Types.ReferenceType, referenceNum: number, correction: string }> | null } };
69+
70+
export type CreateThreadResponseExplainMutationVariables = Types.Exact<{
71+
where: Types.CreateThreadResponseExplainWhereInput;
72+
}>;
73+
74+
75+
export type CreateThreadResponseExplainMutation = { __typename?: 'Mutation', createThreadResponseExplain: any };
6976

7077
export type UpdateThreadMutationVariables = Types.Exact<{
7178
where: Types.ThreadUniqueWhereInput;
@@ -102,7 +109,7 @@ export type CreateCorrectedThreadResponseMutationVariables = Types.Exact<{
102109
}>;
103110

104111

105-
export type CreateCorrectedThreadResponseMutation = { __typename?: 'Mutation', createCorrectedThreadResponse: { __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null, corrections?: Array<{ __typename?: 'CorrectionDetail', id: number, type: Types.ReferenceType, correction: string }> | null } };
112+
export type CreateCorrectedThreadResponseMutation = { __typename?: 'Mutation', createCorrectedThreadResponse: { __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array<string | null> | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null, references?: Array<{ __typename?: 'DetailReference', referenceId?: number | null, summary: string, type: Types.ReferenceType, sqlSnippet?: string | null, sqlLocation?: { __typename?: 'ReferenceSQLLocation', column: number, line: number } | null } | null> | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null, explain?: { __typename?: 'ThreadResponseExplainInfo', queryId?: string | null, status?: Types.ExplainTaskStatus | null, error?: any | null } | null, corrections?: Array<{ __typename?: 'CorrectionDetail', id: number, type: Types.ReferenceType, referenceNum: number, correction: string }> | null } };
106113

107114
export const CommonErrorFragmentDoc = gql`
108115
fragment CommonError on Error {
@@ -125,6 +132,16 @@ export const CommonResponseFragmentDoc = gql`
125132
summary
126133
sql
127134
cteName
135+
references {
136+
referenceId
137+
summary
138+
type
139+
sqlSnippet
140+
sqlLocation {
141+
column
142+
line
143+
}
144+
}
128145
}
129146
view {
130147
id
@@ -133,9 +150,15 @@ export const CommonResponseFragmentDoc = gql`
133150
displayName
134151
}
135152
}
153+
explain {
154+
queryId
155+
status
156+
error
157+
}
136158
corrections {
137159
id
138160
type
161+
referenceNum
139162
correction
140163
}
141164
}
@@ -481,6 +504,37 @@ export function useCreateThreadResponseMutation(baseOptions?: Apollo.MutationHoo
481504
export type CreateThreadResponseMutationHookResult = ReturnType<typeof useCreateThreadResponseMutation>;
482505
export type CreateThreadResponseMutationResult = Apollo.MutationResult<CreateThreadResponseMutation>;
483506
export type CreateThreadResponseMutationOptions = Apollo.BaseMutationOptions<CreateThreadResponseMutation, CreateThreadResponseMutationVariables>;
507+
export const CreateThreadResponseExplainDocument = gql`
508+
mutation CreateThreadResponseExplain($where: CreateThreadResponseExplainWhereInput!) {
509+
createThreadResponseExplain(where: $where)
510+
}
511+
`;
512+
export type CreateThreadResponseExplainMutationFn = Apollo.MutationFunction<CreateThreadResponseExplainMutation, CreateThreadResponseExplainMutationVariables>;
513+
514+
/**
515+
* __useCreateThreadResponseExplainMutation__
516+
*
517+
* To run a mutation, you first call `useCreateThreadResponseExplainMutation` within a React component and pass it any options that fit your needs.
518+
* When your component renders, `useCreateThreadResponseExplainMutation` returns a tuple that includes:
519+
* - A mutate function that you can call at any time to execute the mutation
520+
* - An object with fields that represent the current status of the mutation's execution
521+
*
522+
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
523+
*
524+
* @example
525+
* const [createThreadResponseExplainMutation, { data, loading, error }] = useCreateThreadResponseExplainMutation({
526+
* variables: {
527+
* where: // value for 'where'
528+
* },
529+
* });
530+
*/
531+
export function useCreateThreadResponseExplainMutation(baseOptions?: Apollo.MutationHookOptions<CreateThreadResponseExplainMutation, CreateThreadResponseExplainMutationVariables>) {
532+
const options = {...defaultOptions, ...baseOptions}
533+
return Apollo.useMutation<CreateThreadResponseExplainMutation, CreateThreadResponseExplainMutationVariables>(CreateThreadResponseExplainDocument, options);
534+
}
535+
export type CreateThreadResponseExplainMutationHookResult = ReturnType<typeof useCreateThreadResponseExplainMutation>;
536+
export type CreateThreadResponseExplainMutationResult = Apollo.MutationResult<CreateThreadResponseExplainMutation>;
537+
export type CreateThreadResponseExplainMutationOptions = Apollo.BaseMutationOptions<CreateThreadResponseExplainMutation, CreateThreadResponseExplainMutationVariables>;
484538
export const UpdateThreadDocument = gql`
485539
mutation UpdateThread($where: ThreadUniqueWhereInput!, $data: UpdateThreadInput!) {
486540
updateThread(where: $where, data: $data) {

wren-ui/src/apollo/client/graphql/home.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ const COMMON_RESPONSE = gql`
2222
summary
2323
sql
2424
cteName
25+
references {
26+
referenceId
27+
summary
28+
type
29+
sqlSnippet
30+
sqlLocation {
31+
column
32+
line
33+
}
34+
}
2535
}
2636
view {
2737
id
@@ -30,9 +40,15 @@ const COMMON_RESPONSE = gql`
3040
displayName
3141
}
3242
}
43+
explain {
44+
queryId
45+
status
46+
error
47+
}
3348
corrections {
3449
id
3550
type
51+
referenceNum
3652
correction
3753
}
3854
}
@@ -152,6 +168,14 @@ export const CREATE_THREAD_RESPONSE = gql`
152168
${COMMON_ERROR}
153169
`;
154170

171+
export const CREATE_THREAD_RESPONSE_EXPLAIN = gql`
172+
mutation CreateThreadResponseExplain(
173+
$where: CreateThreadResponseExplainWhereInput!
174+
) {
175+
createThreadResponseExplain(where: $where)
176+
}
177+
`;
178+
155179
export const UPDATE_THREAD = gql`
156180
mutation UpdateThread(
157181
$where: ThreadUniqueWhereInput!

0 commit comments

Comments
 (0)