@graphext/cuery 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/src/schemas/index.d.ts +0 -1
- package/esm/src/schemas/index.d.ts.map +1 -1
- package/esm/src/schemas/sentiment.schema.d.ts +4 -0
- package/esm/src/schemas/sentiment.schema.d.ts.map +1 -1
- package/esm/src/schemas/sentiment.schema.js +6 -2
- package/esm/src/tools/sentiment.d.ts +8 -2
- package/esm/src/tools/sentiment.d.ts.map +1 -1
- package/esm/src/tools/sentiment.js +65 -9
- package/package.json +1 -1
- package/script/src/schemas/index.d.ts +0 -1
- package/script/src/schemas/index.d.ts.map +1 -1
- package/script/src/schemas/sentiment.schema.d.ts +4 -0
- package/script/src/schemas/sentiment.schema.d.ts.map +1 -1
- package/script/src/schemas/sentiment.schema.js +6 -2
- package/script/src/tools/sentiment.d.ts +8 -2
- package/script/src/tools/sentiment.d.ts.map +1 -1
- package/script/src/tools/sentiment.js +65 -9
- package/esm/src/schemas/pipeline.schema.d.ts +0 -146
- package/esm/src/schemas/pipeline.schema.d.ts.map +0 -1
- package/esm/src/schemas/pipeline.schema.js +0 -16
- package/script/src/schemas/pipeline.schema.d.ts +0 -146
- package/script/src/schemas/pipeline.schema.d.ts.map +0 -1
- package/script/src/schemas/pipeline.schema.js +0 -17
|
@@ -14,7 +14,6 @@ export type * from './persona.schema.js';
|
|
|
14
14
|
export type * from './brand.schema.js';
|
|
15
15
|
export type * from './funnel.schema.js';
|
|
16
16
|
export type * from './keyword.schema.js';
|
|
17
|
-
export type * from './pipeline.schema.js';
|
|
18
17
|
export type * from './models.schema.js';
|
|
19
18
|
export type * from './seedKeyword.schema.js';
|
|
20
19
|
export type * from './topics.schema.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/schemas/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,mBAAmB,CAAC;AACvC,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/schemas/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,mBAAmB,CAAC;AACvC,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,yBAAyB,CAAC;AAC7C,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,oBAAoB,CAAC"}
|
|
@@ -6,6 +6,8 @@ export declare const ABSentimentSchema: z.ZodObject<{
|
|
|
6
6
|
negative: "negative";
|
|
7
7
|
}>;
|
|
8
8
|
reason: z.ZodString;
|
|
9
|
+
quote: z.ZodString;
|
|
10
|
+
context: z.ZodNullable<z.ZodString>;
|
|
9
11
|
}, z.core.$strip>;
|
|
10
12
|
export declare const ABSentimentsSchema: z.ZodObject<{
|
|
11
13
|
aspects: z.ZodArray<z.ZodObject<{
|
|
@@ -15,6 +17,8 @@ export declare const ABSentimentsSchema: z.ZodObject<{
|
|
|
15
17
|
negative: "negative";
|
|
16
18
|
}>;
|
|
17
19
|
reason: z.ZodString;
|
|
20
|
+
quote: z.ZodString;
|
|
21
|
+
context: z.ZodNullable<z.ZodString>;
|
|
18
22
|
}, z.core.$strip>>;
|
|
19
23
|
}, z.core.$strip>;
|
|
20
24
|
export type ABSentiment = z.infer<typeof ABSentimentSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sentiment.schema.d.ts","sourceRoot":"","sources":["../../../src/src/schemas/sentiment.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,+CAA+C,CAAC;AAElE,eAAO,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"sentiment.schema.d.ts","sourceRoot":"","sources":["../../../src/src/schemas/sentiment.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,+CAA+C,CAAC;AAElE,eAAO,MAAM,iBAAiB;;;;;;;;;iBAc5B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;iBAE7B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
|
|
@@ -2,8 +2,12 @@ import { z } from '../../deps/jsr.io/@zod/zod/4.3.6/src/index.js';
|
|
|
2
2
|
export const ABSentimentSchema = z.object({
|
|
3
3
|
aspect: z.string().describe('The specific entity or aspect mentioned in the text.'),
|
|
4
4
|
sentiment: z.enum(['positive', 'negative']).describe('The sentiment expressed toward the aspect, either positive or negative.'),
|
|
5
|
-
reason: z.string().describe('A brief explanation of why this sentiment was assigned to the aspect.')
|
|
5
|
+
reason: z.string().describe('A brief explanation of why this sentiment was assigned to the aspect.'),
|
|
6
|
+
quote: z.string().min(1).refine((val) => val.trim().length > 0, {
|
|
7
|
+
message: 'Quote must not be empty or whitespace-only',
|
|
8
|
+
}).describe('The exact text fragment from the input containing both the aspect and the sentiment expressed about it.'),
|
|
9
|
+
context: z.string().nullable().describe('Optional contextual information about the aspect, such as the brand or entity it relates to.'),
|
|
6
10
|
});
|
|
7
11
|
export const ABSentimentsSchema = z.object({
|
|
8
|
-
aspects: z.array(ABSentimentSchema).describe('A list of aspects with their associated sentiments and
|
|
12
|
+
aspects: z.array(ABSentimentSchema).describe('A list of aspects with their associated sentiments, reasons, quotes, and optional context.')
|
|
9
13
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Message } from '../llm.js';
|
|
1
|
+
import type { LLMResponse, Message } from '../llm.js';
|
|
2
2
|
import type { BrandContext } from '../schemas/brand.schema.js';
|
|
3
3
|
import { type ABSentiment, type ABSentiments } from '../schemas/sentiment.schema.js';
|
|
4
|
-
import {
|
|
4
|
+
import { type ModelConfig, Tool } from '../tool.js';
|
|
5
5
|
import { Classifier } from './classifier.js';
|
|
6
6
|
export interface SentimentExtractorConfig {
|
|
7
7
|
/** Additional instructions for sentiment extraction */
|
|
@@ -23,11 +23,17 @@ export declare class SentimentExtractor extends Tool<string | null, ABSentiments
|
|
|
23
23
|
negative: "negative";
|
|
24
24
|
}>;
|
|
25
25
|
reason: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString;
|
|
26
|
+
quote: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString;
|
|
27
|
+
context: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodNullable<import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString>;
|
|
26
28
|
}, import("../../deps/jsr.io/@zod/zod/4.3.6/src/v4/core/schemas.js").$strip>>;
|
|
27
29
|
}, import("../../deps/jsr.io/@zod/zod/4.3.6/src/v4/core/schemas.js").$strip>;
|
|
28
30
|
protected prompt(text: string | null): Message[];
|
|
29
31
|
protected isEmpty(text: string | null): boolean;
|
|
30
32
|
protected extractResult(parsed: ABSentiments): Array<ABSentiment>;
|
|
33
|
+
/**
|
|
34
|
+
* Override invoke to add quote validation
|
|
35
|
+
*/
|
|
36
|
+
invoke(input: string | null, options?: Partial<ModelConfig>): Promise<LLMResponse<Array<ABSentiment> | null>>;
|
|
31
37
|
}
|
|
32
38
|
/**
|
|
33
39
|
* Sentiment polarity labels for classification.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sentiment.d.ts","sourceRoot":"","sources":["../../../src/src/tools/sentiment.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"sentiment.d.ts","sourceRoot":"","sources":["../../../src/src/tools/sentiment.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAW,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAsB,MAAM,gCAAgC,CAAC;AACzG,OAAO,EAAE,KAAK,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AA6D7C,MAAM,WAAW,wBAAwB;IACxC,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,KAAK,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CAC5B;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAC5F,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,MAAM,EAAE,wBAAwB,YAAK,EAAE,WAAW,EAAE,WAAW;cAuBxD,MAAM;;;;;;;;;;;;IAIzB,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,EAAE;cAQ7B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;cAIrC,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC;IAI1E;;OAEG;IACY,MAAM,CACpB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,OAAO,GAAE,OAAO,CAAC,WAAW,CAAM,GAChC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC;CA+BlD;AAMD;;GAEG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAI5D,CAAC;AAWF;;GAEG;AACH,MAAM,WAAW,iCAAiC;IACjD,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,2BAA4B,SAAQ,UAAU;gBAC9C,MAAM,EAAE,iCAAiC,YAAK,EAAE,WAAW,EAAE,WAAW;CAOpF;AAED,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACvF,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC"}
|
|
@@ -2,6 +2,15 @@ import { dedent } from '../helpers/utils.js';
|
|
|
2
2
|
import { ABSentimentsSchema } from '../schemas/sentiment.schema.js';
|
|
3
3
|
import { Tool } from '../tool.js';
|
|
4
4
|
import { Classifier } from './classifier.js';
|
|
5
|
+
/**
|
|
6
|
+
* Formats a portfolio array as a comma-separated list of product/service names.
|
|
7
|
+
* Includes category in parentheses if available.
|
|
8
|
+
*/
|
|
9
|
+
function formatPortfolio(portfolio) {
|
|
10
|
+
return portfolio
|
|
11
|
+
.map((p) => (p.category ? `${p.name} (${p.category})` : p.name))
|
|
12
|
+
.join(', ');
|
|
13
|
+
}
|
|
5
14
|
const ABS_PROMPT_SYSTEM = dedent(`
|
|
6
15
|
You're an expert in Aspect-Based Sentiment Analysis. Your task involves identifying specific
|
|
7
16
|
entities mentioned in a text (e.g. a person, product, service, or experience) and determining the
|
|
@@ -15,10 +24,23 @@ Specifically:
|
|
|
15
24
|
a. the aspect as it occurs in the text (key "aspect")
|
|
16
25
|
b. the sentiment label as either "positive" or "negative" (key "sentiment")
|
|
17
26
|
c. the reason for the sentiment assignment as a short text (key "reason")
|
|
27
|
+
d. the exact text fragment containing both the aspect and what is said about it (key "quote") - must be a verbatim substring
|
|
28
|
+
e. optional contextual information about the aspect, such as the brand or entity it relates to (key "context") - use null if not applicable
|
|
18
29
|
4. If there are no sentiment-bearing aspects in the text, the output should be an empty list
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
|
|
31
|
+
IMPORTANT: The "quote" field must be an EXACT verbatim substring from the input text. It should
|
|
32
|
+
include the complete phrase mentioning both the aspect and the sentiment expressed about it.
|
|
33
|
+
|
|
34
|
+
Example:
|
|
35
|
+
|
|
36
|
+
Input text: "The room service at the Grand Hotel was absolutely terrible and the staff were rude, but the view from our room was breathtaking."
|
|
37
|
+
|
|
38
|
+
Output:
|
|
39
|
+
[
|
|
40
|
+
{"aspect": "The room service at the Grand Hotel", "sentiment": "negative", "reason": "Described as terrible.", "quote": "The room service at the Grand Hotel was absolutely terrible", "context": "Grand Hotel"},
|
|
41
|
+
{"aspect": "the staff", "sentiment": "negative", "reason": "Described as rude.", "quote": "the staff were rude", "context": "Grand Hotel"},
|
|
42
|
+
{"aspect": "the view from our room", "sentiment": "positive", "reason": "Described as breathtaking.", "quote": "the view from our room was breathtaking", "context": "Grand Hotel"}
|
|
43
|
+
]
|
|
22
44
|
|
|
23
45
|
Only extract aspects that have an explicitly expressed sentiment associated with them, i.e.
|
|
24
46
|
subjective opinions, feelings, or evaluations. Do not infer sentiment from factual statements,
|
|
@@ -45,11 +67,18 @@ export class SentimentExtractor extends Tool {
|
|
|
45
67
|
super(modelConfig);
|
|
46
68
|
const { instructions = '', brand = null } = config;
|
|
47
69
|
const brandInstructions = brand
|
|
48
|
-
?
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
70
|
+
? (() => {
|
|
71
|
+
const portfolio = formatPortfolio(brand.portfolio);
|
|
72
|
+
const portfolioText = portfolio
|
|
73
|
+
? ` or its products/services (${portfolio})`
|
|
74
|
+
: '';
|
|
75
|
+
return dedent(`
|
|
76
|
+
Pay special attention to mentions of "${brand.shortName}"${portfolioText}.
|
|
77
|
+
When an aspect relates to a brand/entity, set the "context" field to "${brand.shortName}".
|
|
78
|
+
Keep aspect names and quoted text exactly as they appear in the original input.
|
|
79
|
+
Respond in language code ${brand.language}.
|
|
80
|
+
`);
|
|
81
|
+
})()
|
|
53
82
|
: '';
|
|
54
83
|
const combinedInstructions = [instructions, brandInstructions].filter(Boolean).join('\n\n');
|
|
55
84
|
this.systemPrompt = ABS_PROMPT_SYSTEM.replace('{instructions}', combinedInstructions);
|
|
@@ -61,7 +90,7 @@ export class SentimentExtractor extends Tool {
|
|
|
61
90
|
const userPrompt = ABS_PROMPT_USER.replace('{text}', text ?? '');
|
|
62
91
|
return [
|
|
63
92
|
{ role: 'system', content: this.systemPrompt },
|
|
64
|
-
{ role: 'user', content: userPrompt }
|
|
93
|
+
{ role: 'user', content: userPrompt },
|
|
65
94
|
];
|
|
66
95
|
}
|
|
67
96
|
isEmpty(text) {
|
|
@@ -70,6 +99,33 @@ export class SentimentExtractor extends Tool {
|
|
|
70
99
|
extractResult(parsed) {
|
|
71
100
|
return parsed.aspects;
|
|
72
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Override invoke to add quote validation
|
|
104
|
+
*/
|
|
105
|
+
async invoke(input, options = {}) {
|
|
106
|
+
const response = await super.invoke(input, options);
|
|
107
|
+
// If we have a successful result and non-empty input, validate quotes
|
|
108
|
+
if (response.parsed && input && input.trim() !== '') {
|
|
109
|
+
const validatedResult = response.parsed.filter((sentiment) => {
|
|
110
|
+
// Check that quote is non-empty and not just whitespace
|
|
111
|
+
if (!sentiment.quote || sentiment.quote.trim().length === 0) {
|
|
112
|
+
console.warn(`Empty or whitespace-only quote for aspect "${sentiment.aspect}"`);
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
// Check that quote is a substring of the input
|
|
116
|
+
if (!input.includes(sentiment.quote)) {
|
|
117
|
+
console.warn(`Quote not found in text: "${sentiment.quote}" for aspect "${sentiment.aspect}"`);
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
});
|
|
122
|
+
return {
|
|
123
|
+
...response,
|
|
124
|
+
parsed: validatedResult,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return response;
|
|
128
|
+
}
|
|
73
129
|
}
|
|
74
130
|
// =============================================================================
|
|
75
131
|
// SentimentPolarityClassifier (overall sentiment polarity)
|
|
@@ -80,7 +136,7 @@ export class SentimentExtractor extends Tool {
|
|
|
80
136
|
export const SENTIMENT_POLARITY_LABELS = {
|
|
81
137
|
positive: 'Expresses favorable opinions, approval, satisfaction, or optimism.',
|
|
82
138
|
neutral: 'No clear sentiment expressed; factual, balanced, or ambiguous.',
|
|
83
|
-
negative: 'Expresses unfavorable opinions, criticism, dissatisfaction, or pessimism.'
|
|
139
|
+
negative: 'Expresses unfavorable opinions, criticism, dissatisfaction, or pessimism.',
|
|
84
140
|
};
|
|
85
141
|
/**
|
|
86
142
|
* Predefined instructions for sentiment polarity classification.
|
package/package.json
CHANGED
|
@@ -14,7 +14,6 @@ export type * from './persona.schema.js';
|
|
|
14
14
|
export type * from './brand.schema.js';
|
|
15
15
|
export type * from './funnel.schema.js';
|
|
16
16
|
export type * from './keyword.schema.js';
|
|
17
|
-
export type * from './pipeline.schema.js';
|
|
18
17
|
export type * from './models.schema.js';
|
|
19
18
|
export type * from './seedKeyword.schema.js';
|
|
20
19
|
export type * from './topics.schema.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/schemas/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,mBAAmB,CAAC;AACvC,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/schemas/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,mBAAmB,CAAC;AACvC,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,yBAAyB,CAAC;AAC7C,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,oBAAoB,CAAC"}
|
|
@@ -6,6 +6,8 @@ export declare const ABSentimentSchema: z.ZodObject<{
|
|
|
6
6
|
negative: "negative";
|
|
7
7
|
}>;
|
|
8
8
|
reason: z.ZodString;
|
|
9
|
+
quote: z.ZodString;
|
|
10
|
+
context: z.ZodNullable<z.ZodString>;
|
|
9
11
|
}, z.core.$strip>;
|
|
10
12
|
export declare const ABSentimentsSchema: z.ZodObject<{
|
|
11
13
|
aspects: z.ZodArray<z.ZodObject<{
|
|
@@ -15,6 +17,8 @@ export declare const ABSentimentsSchema: z.ZodObject<{
|
|
|
15
17
|
negative: "negative";
|
|
16
18
|
}>;
|
|
17
19
|
reason: z.ZodString;
|
|
20
|
+
quote: z.ZodString;
|
|
21
|
+
context: z.ZodNullable<z.ZodString>;
|
|
18
22
|
}, z.core.$strip>>;
|
|
19
23
|
}, z.core.$strip>;
|
|
20
24
|
export type ABSentiment = z.infer<typeof ABSentimentSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sentiment.schema.d.ts","sourceRoot":"","sources":["../../../src/src/schemas/sentiment.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,+CAA+C,CAAC;AAElE,eAAO,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"sentiment.schema.d.ts","sourceRoot":"","sources":["../../../src/src/schemas/sentiment.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,+CAA+C,CAAC;AAElE,eAAO,MAAM,iBAAiB;;;;;;;;;iBAc5B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;iBAE7B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
|
|
@@ -5,8 +5,12 @@ const index_js_1 = require("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js");
|
|
|
5
5
|
exports.ABSentimentSchema = index_js_1.z.object({
|
|
6
6
|
aspect: index_js_1.z.string().describe('The specific entity or aspect mentioned in the text.'),
|
|
7
7
|
sentiment: index_js_1.z.enum(['positive', 'negative']).describe('The sentiment expressed toward the aspect, either positive or negative.'),
|
|
8
|
-
reason: index_js_1.z.string().describe('A brief explanation of why this sentiment was assigned to the aspect.')
|
|
8
|
+
reason: index_js_1.z.string().describe('A brief explanation of why this sentiment was assigned to the aspect.'),
|
|
9
|
+
quote: index_js_1.z.string().min(1).refine((val) => val.trim().length > 0, {
|
|
10
|
+
message: 'Quote must not be empty or whitespace-only',
|
|
11
|
+
}).describe('The exact text fragment from the input containing both the aspect and the sentiment expressed about it.'),
|
|
12
|
+
context: index_js_1.z.string().nullable().describe('Optional contextual information about the aspect, such as the brand or entity it relates to.'),
|
|
9
13
|
});
|
|
10
14
|
exports.ABSentimentsSchema = index_js_1.z.object({
|
|
11
|
-
aspects: index_js_1.z.array(exports.ABSentimentSchema).describe('A list of aspects with their associated sentiments and
|
|
15
|
+
aspects: index_js_1.z.array(exports.ABSentimentSchema).describe('A list of aspects with their associated sentiments, reasons, quotes, and optional context.')
|
|
12
16
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Message } from '../llm.js';
|
|
1
|
+
import type { LLMResponse, Message } from '../llm.js';
|
|
2
2
|
import type { BrandContext } from '../schemas/brand.schema.js';
|
|
3
3
|
import { type ABSentiment, type ABSentiments } from '../schemas/sentiment.schema.js';
|
|
4
|
-
import {
|
|
4
|
+
import { type ModelConfig, Tool } from '../tool.js';
|
|
5
5
|
import { Classifier } from './classifier.js';
|
|
6
6
|
export interface SentimentExtractorConfig {
|
|
7
7
|
/** Additional instructions for sentiment extraction */
|
|
@@ -23,11 +23,17 @@ export declare class SentimentExtractor extends Tool<string | null, ABSentiments
|
|
|
23
23
|
negative: "negative";
|
|
24
24
|
}>;
|
|
25
25
|
reason: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString;
|
|
26
|
+
quote: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString;
|
|
27
|
+
context: import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodNullable<import("../../deps/jsr.io/@zod/zod/4.3.6/src/index.js").ZodString>;
|
|
26
28
|
}, import("../../deps/jsr.io/@zod/zod/4.3.6/src/v4/core/schemas.js").$strip>>;
|
|
27
29
|
}, import("../../deps/jsr.io/@zod/zod/4.3.6/src/v4/core/schemas.js").$strip>;
|
|
28
30
|
protected prompt(text: string | null): Message[];
|
|
29
31
|
protected isEmpty(text: string | null): boolean;
|
|
30
32
|
protected extractResult(parsed: ABSentiments): Array<ABSentiment>;
|
|
33
|
+
/**
|
|
34
|
+
* Override invoke to add quote validation
|
|
35
|
+
*/
|
|
36
|
+
invoke(input: string | null, options?: Partial<ModelConfig>): Promise<LLMResponse<Array<ABSentiment> | null>>;
|
|
31
37
|
}
|
|
32
38
|
/**
|
|
33
39
|
* Sentiment polarity labels for classification.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sentiment.d.ts","sourceRoot":"","sources":["../../../src/src/tools/sentiment.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"sentiment.d.ts","sourceRoot":"","sources":["../../../src/src/tools/sentiment.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAW,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAsB,MAAM,gCAAgC,CAAC;AACzG,OAAO,EAAE,KAAK,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AA6D7C,MAAM,WAAW,wBAAwB;IACxC,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,KAAK,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CAC5B;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAC5F,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,MAAM,EAAE,wBAAwB,YAAK,EAAE,WAAW,EAAE,WAAW;cAuBxD,MAAM;;;;;;;;;;;;IAIzB,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,EAAE;cAQ7B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;cAIrC,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC;IAI1E;;OAEG;IACY,MAAM,CACpB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,OAAO,GAAE,OAAO,CAAC,WAAW,CAAM,GAChC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC;CA+BlD;AAMD;;GAEG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAI5D,CAAC;AAWF;;GAEG;AACH,MAAM,WAAW,iCAAiC;IACjD,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,2BAA4B,SAAQ,UAAU;gBAC9C,MAAM,EAAE,iCAAiC,YAAK,EAAE,WAAW,EAAE,WAAW;CAOpF;AAED,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACvF,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC"}
|
|
@@ -5,6 +5,15 @@ const utils_js_1 = require("../helpers/utils.js");
|
|
|
5
5
|
const sentiment_schema_js_1 = require("../schemas/sentiment.schema.js");
|
|
6
6
|
const tool_js_1 = require("../tool.js");
|
|
7
7
|
const classifier_js_1 = require("./classifier.js");
|
|
8
|
+
/**
|
|
9
|
+
* Formats a portfolio array as a comma-separated list of product/service names.
|
|
10
|
+
* Includes category in parentheses if available.
|
|
11
|
+
*/
|
|
12
|
+
function formatPortfolio(portfolio) {
|
|
13
|
+
return portfolio
|
|
14
|
+
.map((p) => (p.category ? `${p.name} (${p.category})` : p.name))
|
|
15
|
+
.join(', ');
|
|
16
|
+
}
|
|
8
17
|
const ABS_PROMPT_SYSTEM = (0, utils_js_1.dedent)(`
|
|
9
18
|
You're an expert in Aspect-Based Sentiment Analysis. Your task involves identifying specific
|
|
10
19
|
entities mentioned in a text (e.g. a person, product, service, or experience) and determining the
|
|
@@ -18,10 +27,23 @@ Specifically:
|
|
|
18
27
|
a. the aspect as it occurs in the text (key "aspect")
|
|
19
28
|
b. the sentiment label as either "positive" or "negative" (key "sentiment")
|
|
20
29
|
c. the reason for the sentiment assignment as a short text (key "reason")
|
|
30
|
+
d. the exact text fragment containing both the aspect and what is said about it (key "quote") - must be a verbatim substring
|
|
31
|
+
e. optional contextual information about the aspect, such as the brand or entity it relates to (key "context") - use null if not applicable
|
|
21
32
|
4. If there are no sentiment-bearing aspects in the text, the output should be an empty list
|
|
22
33
|
|
|
23
|
-
|
|
24
|
-
|
|
34
|
+
IMPORTANT: The "quote" field must be an EXACT verbatim substring from the input text. It should
|
|
35
|
+
include the complete phrase mentioning both the aspect and the sentiment expressed about it.
|
|
36
|
+
|
|
37
|
+
Example:
|
|
38
|
+
|
|
39
|
+
Input text: "The room service at the Grand Hotel was absolutely terrible and the staff were rude, but the view from our room was breathtaking."
|
|
40
|
+
|
|
41
|
+
Output:
|
|
42
|
+
[
|
|
43
|
+
{"aspect": "The room service at the Grand Hotel", "sentiment": "negative", "reason": "Described as terrible.", "quote": "The room service at the Grand Hotel was absolutely terrible", "context": "Grand Hotel"},
|
|
44
|
+
{"aspect": "the staff", "sentiment": "negative", "reason": "Described as rude.", "quote": "the staff were rude", "context": "Grand Hotel"},
|
|
45
|
+
{"aspect": "the view from our room", "sentiment": "positive", "reason": "Described as breathtaking.", "quote": "the view from our room was breathtaking", "context": "Grand Hotel"}
|
|
46
|
+
]
|
|
25
47
|
|
|
26
48
|
Only extract aspects that have an explicitly expressed sentiment associated with them, i.e.
|
|
27
49
|
subjective opinions, feelings, or evaluations. Do not infer sentiment from factual statements,
|
|
@@ -48,11 +70,18 @@ class SentimentExtractor extends tool_js_1.Tool {
|
|
|
48
70
|
super(modelConfig);
|
|
49
71
|
const { instructions = '', brand = null } = config;
|
|
50
72
|
const brandInstructions = brand
|
|
51
|
-
? (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
73
|
+
? (() => {
|
|
74
|
+
const portfolio = formatPortfolio(brand.portfolio);
|
|
75
|
+
const portfolioText = portfolio
|
|
76
|
+
? ` or its products/services (${portfolio})`
|
|
77
|
+
: '';
|
|
78
|
+
return (0, utils_js_1.dedent)(`
|
|
79
|
+
Pay special attention to mentions of "${brand.shortName}"${portfolioText}.
|
|
80
|
+
When an aspect relates to a brand/entity, set the "context" field to "${brand.shortName}".
|
|
81
|
+
Keep aspect names and quoted text exactly as they appear in the original input.
|
|
82
|
+
Respond in language code ${brand.language}.
|
|
83
|
+
`);
|
|
84
|
+
})()
|
|
56
85
|
: '';
|
|
57
86
|
const combinedInstructions = [instructions, brandInstructions].filter(Boolean).join('\n\n');
|
|
58
87
|
this.systemPrompt = ABS_PROMPT_SYSTEM.replace('{instructions}', combinedInstructions);
|
|
@@ -64,7 +93,7 @@ class SentimentExtractor extends tool_js_1.Tool {
|
|
|
64
93
|
const userPrompt = ABS_PROMPT_USER.replace('{text}', text ?? '');
|
|
65
94
|
return [
|
|
66
95
|
{ role: 'system', content: this.systemPrompt },
|
|
67
|
-
{ role: 'user', content: userPrompt }
|
|
96
|
+
{ role: 'user', content: userPrompt },
|
|
68
97
|
];
|
|
69
98
|
}
|
|
70
99
|
isEmpty(text) {
|
|
@@ -73,6 +102,33 @@ class SentimentExtractor extends tool_js_1.Tool {
|
|
|
73
102
|
extractResult(parsed) {
|
|
74
103
|
return parsed.aspects;
|
|
75
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Override invoke to add quote validation
|
|
107
|
+
*/
|
|
108
|
+
async invoke(input, options = {}) {
|
|
109
|
+
const response = await super.invoke(input, options);
|
|
110
|
+
// If we have a successful result and non-empty input, validate quotes
|
|
111
|
+
if (response.parsed && input && input.trim() !== '') {
|
|
112
|
+
const validatedResult = response.parsed.filter((sentiment) => {
|
|
113
|
+
// Check that quote is non-empty and not just whitespace
|
|
114
|
+
if (!sentiment.quote || sentiment.quote.trim().length === 0) {
|
|
115
|
+
console.warn(`Empty or whitespace-only quote for aspect "${sentiment.aspect}"`);
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
// Check that quote is a substring of the input
|
|
119
|
+
if (!input.includes(sentiment.quote)) {
|
|
120
|
+
console.warn(`Quote not found in text: "${sentiment.quote}" for aspect "${sentiment.aspect}"`);
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
return true;
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
...response,
|
|
127
|
+
parsed: validatedResult,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return response;
|
|
131
|
+
}
|
|
76
132
|
}
|
|
77
133
|
exports.SentimentExtractor = SentimentExtractor;
|
|
78
134
|
// =============================================================================
|
|
@@ -84,7 +140,7 @@ exports.SentimentExtractor = SentimentExtractor;
|
|
|
84
140
|
exports.SENTIMENT_POLARITY_LABELS = {
|
|
85
141
|
positive: 'Expresses favorable opinions, approval, satisfaction, or optimism.',
|
|
86
142
|
neutral: 'No clear sentiment expressed; factual, balanced, or ambiguous.',
|
|
87
|
-
negative: 'Expresses unfavorable opinions, criticism, dissatisfaction, or pessimism.'
|
|
143
|
+
negative: 'Expresses unfavorable opinions, criticism, dissatisfaction, or pessimism.',
|
|
88
144
|
};
|
|
89
145
|
/**
|
|
90
146
|
* Predefined instructions for sentiment polarity classification.
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pipeline Context Type Definitions
|
|
3
|
-
*
|
|
4
|
-
* These types define the structure for pipeline execution contexts.
|
|
5
|
-
* They are shared between client and server code.
|
|
6
|
-
*
|
|
7
|
-
* IMPORTANT: This type must be kept in sync with the dynamically generated
|
|
8
|
-
* type from: supabase/functions/pipelines/workflows/audit.ts
|
|
9
|
-
*
|
|
10
|
-
* The actual pipeline generates:
|
|
11
|
-
* export type AiAuditPromptsPipelineContext = OrchestratorRunContext<typeof promptsPipeline>;
|
|
12
|
-
*
|
|
13
|
-
* This static definition serves as a contract for client-side usage.
|
|
14
|
-
* It represents the union of all context types required by the pipeline nodes.
|
|
15
|
-
*/
|
|
16
|
-
import type { Brand, BrandContext, FlaggedBrand } from './brand.schema.js';
|
|
17
|
-
import type { Funnel } from './funnel.schema.js';
|
|
18
|
-
import type { ModelIdentifier } from './models.schema.js';
|
|
19
|
-
import type { Persona } from './persona.schema.js';
|
|
20
|
-
import type { TopicType } from './topics.schema.js';
|
|
21
|
-
export interface KeywordPlannerOptions {
|
|
22
|
-
url?: string;
|
|
23
|
-
urlAsExpandRelevanceContext?: string;
|
|
24
|
-
generateIdeasFromSeeds?: boolean;
|
|
25
|
-
}
|
|
26
|
-
export interface AiAuditPromptsPipelineOptions {
|
|
27
|
-
filterLowRelevanceKeywords?: boolean;
|
|
28
|
-
/** When true, adds deduplicatedKeywords column with all keywords sharing the same metrics */
|
|
29
|
-
includeDeduplicatedKeywords?: boolean;
|
|
30
|
-
/** When true, includes seedKeywords column in output records. Defaults to false. */
|
|
31
|
-
includeSeedKeywords?: boolean;
|
|
32
|
-
/** When true, generates a separate dataset with all keywords (dedup by keyword only). Defaults to false. */
|
|
33
|
-
includeAllKeywordsDataset?: boolean;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* AI Audit Pipeline Request Structure
|
|
37
|
-
*
|
|
38
|
-
* This represents the structure of the request sent to the /pipelines/run endpoint.
|
|
39
|
-
* The `context` field should match the AiAuditPromptsPipelineContext from the orchestrator.
|
|
40
|
-
*/
|
|
41
|
-
export interface AiAuditPromptsPipelineRequest {
|
|
42
|
-
pipelineName: 'promptsPipeline';
|
|
43
|
-
context: AiAuditPromptsPipelineContext;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* AI Audit Answers Pipeline Request Structure
|
|
47
|
-
*
|
|
48
|
-
* This represents the structure of the request sent to the /pipelines/run endpoint.
|
|
49
|
-
* The `context` field should match the AiAuditAnswersPipelineContext from the orchestrator.
|
|
50
|
-
*/
|
|
51
|
-
export interface AiAuditAnswersPipelineRequest {
|
|
52
|
-
pipelineName: 'answersPipeline';
|
|
53
|
-
context: AiAuditAnswersPipelineContext;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* AI Audit Prompts Pipeline Context Data - Static Definition
|
|
57
|
-
*
|
|
58
|
-
* This represents the union of all context parameters required by the
|
|
59
|
-
* various nodes in the AI audit prompts pipeline:
|
|
60
|
-
*
|
|
61
|
-
* - { keywordPlanner }: Keyword Planner parameters & seed sources
|
|
62
|
-
* - { options }: Pipeline-level flags
|
|
63
|
-
* - { workspaceId, projectName }: Project creation parameters
|
|
64
|
-
* - { funnel }: Funnel assignment parameters
|
|
65
|
-
* - { brand }: Brand-specific processing parameters
|
|
66
|
-
* - { brands }: Brand collection parameters
|
|
67
|
-
*/
|
|
68
|
-
export interface AiAuditPromptsPipelineContext {
|
|
69
|
-
clientUserEmail: string;
|
|
70
|
-
workspaceId: number;
|
|
71
|
-
projectName?: string;
|
|
72
|
-
/** Optional existing project to append prompts into. */
|
|
73
|
-
projectId?: number;
|
|
74
|
-
keywordPlanner: KeywordPlannerOptions;
|
|
75
|
-
/** ISO 639-1 language code for prompts/keywords (e.g., "en"). */
|
|
76
|
-
languageCode?: string;
|
|
77
|
-
/** ISO 3166-1 alpha-2 country code to localize sources (e.g., "US"). */
|
|
78
|
-
countryISOCode?: string;
|
|
79
|
-
/**
|
|
80
|
-
* Custom prompts provided by the user.
|
|
81
|
-
* These go directly to the prompt dataset without keyword expansion.
|
|
82
|
-
*/
|
|
83
|
-
directPrompts?: Array<string>;
|
|
84
|
-
/**
|
|
85
|
-
* Custom seed keywords provided by the user.
|
|
86
|
-
* These are processed through keyword expansion like other seed keywords.
|
|
87
|
-
*/
|
|
88
|
-
customSeedKeywords?: Array<string>;
|
|
89
|
-
funnel?: Funnel;
|
|
90
|
-
brand: BrandContext;
|
|
91
|
-
competitors: Array<FlaggedBrand | Brand>;
|
|
92
|
-
personas: Array<Persona>;
|
|
93
|
-
options?: AiAuditPromptsPipelineOptions;
|
|
94
|
-
topics?: Array<TopicType>;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* AI Audit Answers Pipeline Context Data
|
|
98
|
-
*
|
|
99
|
-
* Context parameters required by the answers pipeline.
|
|
100
|
-
*/
|
|
101
|
-
export interface AiAuditAnswersPipelineContext {
|
|
102
|
-
clientUserEmail: string;
|
|
103
|
-
projectId: number;
|
|
104
|
-
promptIds: Array<number>;
|
|
105
|
-
models: Array<ModelIdentifier>;
|
|
106
|
-
countryISOCode?: string;
|
|
107
|
-
brand: BrandContext;
|
|
108
|
-
competitors?: Array<FlaggedBrand | Brand>;
|
|
109
|
-
/**
|
|
110
|
-
* Panel ID for grouping answers by execution source.
|
|
111
|
-
* When present (scheduled cron execution), answers are grouped by panelId.
|
|
112
|
-
*/
|
|
113
|
-
panelId?: number;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Persisted project configuration (pipeline context without user metadata).
|
|
117
|
-
*/
|
|
118
|
-
export type AiAuditProjectConfig = Omit<AiAuditPromptsPipelineContext, 'clientUserEmail' | 'projectId'>;
|
|
119
|
-
/**
|
|
120
|
-
* Topic Update Pipeline Request Structure
|
|
121
|
-
*
|
|
122
|
-
* This represents the structure of the request sent to the /pipelines/run endpoint
|
|
123
|
-
* for updating topic hierarchy in existing prompts.
|
|
124
|
-
*/
|
|
125
|
-
export interface TopicUpdatePipelineRequest {
|
|
126
|
-
pipelineName: 'topicUpdatePipeline';
|
|
127
|
-
context: TopicUpdatePipelineContext;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Topic Update Pipeline Context Data
|
|
131
|
-
*
|
|
132
|
-
* Context parameters required by the topic update pipeline.
|
|
133
|
-
* This pipeline downloads the prompts dataset, re-assigns topics using AI
|
|
134
|
-
* based on the provided taxonomy, and uploads the updated dataset back to the project.
|
|
135
|
-
*/
|
|
136
|
-
export interface TopicUpdatePipelineContext {
|
|
137
|
-
clientUserEmail: string;
|
|
138
|
-
projectId: number;
|
|
139
|
-
/**
|
|
140
|
-
* The topics taxonomy to use for assigning topics.
|
|
141
|
-
* Each topic contains a name and a list of subtopics.
|
|
142
|
-
* The AI will classify each prompt into the appropriate topic/subtopic.
|
|
143
|
-
*/
|
|
144
|
-
topics: Array<TopicType>;
|
|
145
|
-
}
|
|
146
|
-
//# sourceMappingURL=pipeline.schema.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.schema.d.ts","sourceRoot":"","sources":["../../../src/src/schemas/pipeline.schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pipeline Context Type Definitions
|
|
3
|
-
*
|
|
4
|
-
* These types define the structure for pipeline execution contexts.
|
|
5
|
-
* They are shared between client and server code.
|
|
6
|
-
*
|
|
7
|
-
* IMPORTANT: This type must be kept in sync with the dynamically generated
|
|
8
|
-
* type from: supabase/functions/pipelines/workflows/audit.ts
|
|
9
|
-
*
|
|
10
|
-
* The actual pipeline generates:
|
|
11
|
-
* export type AiAuditPromptsPipelineContext = OrchestratorRunContext<typeof promptsPipeline>;
|
|
12
|
-
*
|
|
13
|
-
* This static definition serves as a contract for client-side usage.
|
|
14
|
-
* It represents the union of all context types required by the pipeline nodes.
|
|
15
|
-
*/
|
|
16
|
-
export {};
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pipeline Context Type Definitions
|
|
3
|
-
*
|
|
4
|
-
* These types define the structure for pipeline execution contexts.
|
|
5
|
-
* They are shared between client and server code.
|
|
6
|
-
*
|
|
7
|
-
* IMPORTANT: This type must be kept in sync with the dynamically generated
|
|
8
|
-
* type from: supabase/functions/pipelines/workflows/audit.ts
|
|
9
|
-
*
|
|
10
|
-
* The actual pipeline generates:
|
|
11
|
-
* export type AiAuditPromptsPipelineContext = OrchestratorRunContext<typeof promptsPipeline>;
|
|
12
|
-
*
|
|
13
|
-
* This static definition serves as a contract for client-side usage.
|
|
14
|
-
* It represents the union of all context types required by the pipeline nodes.
|
|
15
|
-
*/
|
|
16
|
-
import type { Brand, BrandContext, FlaggedBrand } from './brand.schema.js';
|
|
17
|
-
import type { Funnel } from './funnel.schema.js';
|
|
18
|
-
import type { ModelIdentifier } from './models.schema.js';
|
|
19
|
-
import type { Persona } from './persona.schema.js';
|
|
20
|
-
import type { TopicType } from './topics.schema.js';
|
|
21
|
-
export interface KeywordPlannerOptions {
|
|
22
|
-
url?: string;
|
|
23
|
-
urlAsExpandRelevanceContext?: string;
|
|
24
|
-
generateIdeasFromSeeds?: boolean;
|
|
25
|
-
}
|
|
26
|
-
export interface AiAuditPromptsPipelineOptions {
|
|
27
|
-
filterLowRelevanceKeywords?: boolean;
|
|
28
|
-
/** When true, adds deduplicatedKeywords column with all keywords sharing the same metrics */
|
|
29
|
-
includeDeduplicatedKeywords?: boolean;
|
|
30
|
-
/** When true, includes seedKeywords column in output records. Defaults to false. */
|
|
31
|
-
includeSeedKeywords?: boolean;
|
|
32
|
-
/** When true, generates a separate dataset with all keywords (dedup by keyword only). Defaults to false. */
|
|
33
|
-
includeAllKeywordsDataset?: boolean;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* AI Audit Pipeline Request Structure
|
|
37
|
-
*
|
|
38
|
-
* This represents the structure of the request sent to the /pipelines/run endpoint.
|
|
39
|
-
* The `context` field should match the AiAuditPromptsPipelineContext from the orchestrator.
|
|
40
|
-
*/
|
|
41
|
-
export interface AiAuditPromptsPipelineRequest {
|
|
42
|
-
pipelineName: 'promptsPipeline';
|
|
43
|
-
context: AiAuditPromptsPipelineContext;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* AI Audit Answers Pipeline Request Structure
|
|
47
|
-
*
|
|
48
|
-
* This represents the structure of the request sent to the /pipelines/run endpoint.
|
|
49
|
-
* The `context` field should match the AiAuditAnswersPipelineContext from the orchestrator.
|
|
50
|
-
*/
|
|
51
|
-
export interface AiAuditAnswersPipelineRequest {
|
|
52
|
-
pipelineName: 'answersPipeline';
|
|
53
|
-
context: AiAuditAnswersPipelineContext;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* AI Audit Prompts Pipeline Context Data - Static Definition
|
|
57
|
-
*
|
|
58
|
-
* This represents the union of all context parameters required by the
|
|
59
|
-
* various nodes in the AI audit prompts pipeline:
|
|
60
|
-
*
|
|
61
|
-
* - { keywordPlanner }: Keyword Planner parameters & seed sources
|
|
62
|
-
* - { options }: Pipeline-level flags
|
|
63
|
-
* - { workspaceId, projectName }: Project creation parameters
|
|
64
|
-
* - { funnel }: Funnel assignment parameters
|
|
65
|
-
* - { brand }: Brand-specific processing parameters
|
|
66
|
-
* - { brands }: Brand collection parameters
|
|
67
|
-
*/
|
|
68
|
-
export interface AiAuditPromptsPipelineContext {
|
|
69
|
-
clientUserEmail: string;
|
|
70
|
-
workspaceId: number;
|
|
71
|
-
projectName?: string;
|
|
72
|
-
/** Optional existing project to append prompts into. */
|
|
73
|
-
projectId?: number;
|
|
74
|
-
keywordPlanner: KeywordPlannerOptions;
|
|
75
|
-
/** ISO 639-1 language code for prompts/keywords (e.g., "en"). */
|
|
76
|
-
languageCode?: string;
|
|
77
|
-
/** ISO 3166-1 alpha-2 country code to localize sources (e.g., "US"). */
|
|
78
|
-
countryISOCode?: string;
|
|
79
|
-
/**
|
|
80
|
-
* Custom prompts provided by the user.
|
|
81
|
-
* These go directly to the prompt dataset without keyword expansion.
|
|
82
|
-
*/
|
|
83
|
-
directPrompts?: Array<string>;
|
|
84
|
-
/**
|
|
85
|
-
* Custom seed keywords provided by the user.
|
|
86
|
-
* These are processed through keyword expansion like other seed keywords.
|
|
87
|
-
*/
|
|
88
|
-
customSeedKeywords?: Array<string>;
|
|
89
|
-
funnel?: Funnel;
|
|
90
|
-
brand: BrandContext;
|
|
91
|
-
competitors: Array<FlaggedBrand | Brand>;
|
|
92
|
-
personas: Array<Persona>;
|
|
93
|
-
options?: AiAuditPromptsPipelineOptions;
|
|
94
|
-
topics?: Array<TopicType>;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* AI Audit Answers Pipeline Context Data
|
|
98
|
-
*
|
|
99
|
-
* Context parameters required by the answers pipeline.
|
|
100
|
-
*/
|
|
101
|
-
export interface AiAuditAnswersPipelineContext {
|
|
102
|
-
clientUserEmail: string;
|
|
103
|
-
projectId: number;
|
|
104
|
-
promptIds: Array<number>;
|
|
105
|
-
models: Array<ModelIdentifier>;
|
|
106
|
-
countryISOCode?: string;
|
|
107
|
-
brand: BrandContext;
|
|
108
|
-
competitors?: Array<FlaggedBrand | Brand>;
|
|
109
|
-
/**
|
|
110
|
-
* Panel ID for grouping answers by execution source.
|
|
111
|
-
* When present (scheduled cron execution), answers are grouped by panelId.
|
|
112
|
-
*/
|
|
113
|
-
panelId?: number;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Persisted project configuration (pipeline context without user metadata).
|
|
117
|
-
*/
|
|
118
|
-
export type AiAuditProjectConfig = Omit<AiAuditPromptsPipelineContext, 'clientUserEmail' | 'projectId'>;
|
|
119
|
-
/**
|
|
120
|
-
* Topic Update Pipeline Request Structure
|
|
121
|
-
*
|
|
122
|
-
* This represents the structure of the request sent to the /pipelines/run endpoint
|
|
123
|
-
* for updating topic hierarchy in existing prompts.
|
|
124
|
-
*/
|
|
125
|
-
export interface TopicUpdatePipelineRequest {
|
|
126
|
-
pipelineName: 'topicUpdatePipeline';
|
|
127
|
-
context: TopicUpdatePipelineContext;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Topic Update Pipeline Context Data
|
|
131
|
-
*
|
|
132
|
-
* Context parameters required by the topic update pipeline.
|
|
133
|
-
* This pipeline downloads the prompts dataset, re-assigns topics using AI
|
|
134
|
-
* based on the provided taxonomy, and uploads the updated dataset back to the project.
|
|
135
|
-
*/
|
|
136
|
-
export interface TopicUpdatePipelineContext {
|
|
137
|
-
clientUserEmail: string;
|
|
138
|
-
projectId: number;
|
|
139
|
-
/**
|
|
140
|
-
* The topics taxonomy to use for assigning topics.
|
|
141
|
-
* Each topic contains a name and a list of subtopics.
|
|
142
|
-
* The AI will classify each prompt into the appropriate topic/subtopic.
|
|
143
|
-
*/
|
|
144
|
-
topics: Array<TopicType>;
|
|
145
|
-
}
|
|
146
|
-
//# sourceMappingURL=pipeline.schema.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.schema.d.ts","sourceRoot":"","sources":["../../../src/src/schemas/pipeline.schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Pipeline Context Type Definitions
|
|
4
|
-
*
|
|
5
|
-
* These types define the structure for pipeline execution contexts.
|
|
6
|
-
* They are shared between client and server code.
|
|
7
|
-
*
|
|
8
|
-
* IMPORTANT: This type must be kept in sync with the dynamically generated
|
|
9
|
-
* type from: supabase/functions/pipelines/workflows/audit.ts
|
|
10
|
-
*
|
|
11
|
-
* The actual pipeline generates:
|
|
12
|
-
* export type AiAuditPromptsPipelineContext = OrchestratorRunContext<typeof promptsPipeline>;
|
|
13
|
-
*
|
|
14
|
-
* This static definition serves as a contract for client-side usage.
|
|
15
|
-
* It represents the union of all context types required by the pipeline nodes.
|
|
16
|
-
*/
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|