@garrix82/reactgenie-dsl 1.0.1 → 1.0.2
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/.env +10 -0
- package/.env.example +17 -0
- package/.github/workflows/publish.yml +20 -0
- package/package.json +1 -5
- package/dist/__test__/dsl-descriptor.test.d.ts +0 -1
- package/dist/__test__/dsl-descriptor.test.js +0 -27
- package/dist/__test__/dsl-descriptor.test.js.map +0 -1
- package/dist/__test__/example_descriptor.d.ts +0 -125
- package/dist/__test__/example_descriptor.js +0 -607
- package/dist/__test__/example_descriptor.js.map +0 -1
- package/dist/__test__/food_descriptor.state.json +0 -1
- package/dist/__test__/food_descriptor.test.d.ts +0 -74
- package/dist/__test__/food_descriptor.test.js +0 -205
- package/dist/__test__/food_descriptor.test.js.map +0 -1
- package/dist/__test__/nl-interpreter-provider-selection.test.d.ts +0 -1
- package/dist/__test__/nl-interpreter-provider-selection.test.js +0 -73
- package/dist/__test__/nl-interpreter-provider-selection.test.js.map +0 -1
- package/dist/__test__/nl-interpreter.test.d.ts +0 -1
- package/dist/__test__/nl-interpreter.test.js +0 -86
- package/dist/__test__/nl-interpreter.test.js.map +0 -1
- package/dist/decorators/__test__/decorators.test.d.ts +0 -1
- package/dist/decorators/__test__/decorators.test.js +0 -182
- package/dist/decorators/__test__/decorators.test.js.map +0 -1
- package/dist/decorators/__test__/inheritance-descriptor.test.d.ts +0 -1
- package/dist/decorators/__test__/inheritance-descriptor.test.js +0 -107
- package/dist/decorators/__test__/inheritance-descriptor.test.js.map +0 -1
- package/dist/dsl/__test__/dsl-interpreter.test.d.ts +0 -1
- package/dist/dsl/__test__/dsl-interpreter.test.js +0 -334
- package/dist/dsl/__test__/dsl-interpreter.test.js.map +0 -1
- package/dist/dsl/__test__/parser.gen.test.d.ts +0 -1
- package/dist/dsl/__test__/parser.gen.test.js +0 -283
- package/dist/dsl/__test__/parser.gen.test.js.map +0 -1
- package/dist/nl/__test__/context-aware-prompt.test.d.ts +0 -1
- package/dist/nl/__test__/context-aware-prompt.test.js +0 -247
- package/dist/nl/__test__/context-aware-prompt.test.js.map +0 -1
- package/dist/nl/__test__/context-selector.test.d.ts +0 -1
- package/dist/nl/__test__/context-selector.test.js +0 -20
- package/dist/nl/__test__/context-selector.test.js.map +0 -1
- package/dist/nl/__test__/nl-parser-groq-transport.test.d.ts +0 -1
- package/dist/nl/__test__/nl-parser-groq-transport.test.js +0 -87
- package/dist/nl/__test__/nl-parser-groq-transport.test.js.map +0 -1
- package/dist/nl/__test__/nl-parser-openai-parity.test.d.ts +0 -1
- package/dist/nl/__test__/nl-parser-openai-parity.test.js +0 -206
- package/dist/nl/__test__/nl-parser-openai-parity.test.js.map +0 -1
- package/dist/nl/__test__/nl-parser-openai-sampling.test.d.ts +0 -1
- package/dist/nl/__test__/nl-parser-openai-sampling.test.js +0 -44
- package/dist/nl/__test__/nl-parser-openai-sampling.test.js.map +0 -1
- package/dist/nl/__test__/nl-parser-openai-transport.test.d.ts +0 -1
- package/dist/nl/__test__/nl-parser-openai-transport.test.js +0 -55
- package/dist/nl/__test__/nl-parser-openai-transport.test.js.map +0 -1
- package/dist/nl/__test__/nl-parser-utils.test.d.ts +0 -1
- package/dist/nl/__test__/nl-parser-utils.test.js +0 -70
- package/dist/nl/__test__/nl-parser-utils.test.js.map +0 -1
- package/dist/nl/__test__/nl-parser.test.d.ts +0 -1
- package/dist/nl/__test__/nl-parser.test.js +0 -64
- package/dist/nl/__test__/nl-parser.test.js.map +0 -1
- package/dist/nl/__test__/parameter-tuning.test.d.ts +0 -1
- package/dist/nl/__test__/parameter-tuning.test.js +0 -95
- package/dist/nl/__test__/parameter-tuning.test.js.map +0 -1
- package/dist/nl/__test__/semantic-parsing-experiment.test.d.ts +0 -1
- package/dist/nl/__test__/semantic-parsing-experiment.test.js +0 -178
- package/dist/nl/__test__/semantic-parsing-experiment.test.js.map +0 -1
- package/dist/nl/llm-monitoring.test.d.ts +0 -5
- package/dist/nl/llm-monitoring.test.js +0 -101
- package/dist/nl/llm-monitoring.test.js.map +0 -1
- package/lib/__test__/dsl-descriptor.test.ts +0 -27
- package/lib/__test__/example_descriptor.ts +0 -762
- package/lib/__test__/food_descriptor.state.json +0 -1
- package/lib/__test__/food_descriptor.test.ts +0 -331
- package/lib/__test__/nl-interpreter-provider-selection.test.ts +0 -126
- package/lib/__test__/nl-interpreter.test.ts +0 -129
- package/lib/decorators/__test__/decorators.test.ts +0 -177
- package/lib/decorators/__test__/inheritance-descriptor.test.ts +0 -92
- package/lib/decorators/decorators.ts +0 -754
- package/lib/decorators/index.ts +0 -2
- package/lib/decorators/store.ts +0 -47
- package/lib/dsl/__test__/dsl-interpreter.test.ts +0 -453
- package/lib/dsl/__test__/parser.gen.test.ts +0 -296
- package/lib/dsl/dsl-interpreter.ts +0 -974
- package/lib/dsl/index.ts +0 -1
- package/lib/dsl/parser.gen.js +0 -1479
- package/lib/dsl/parser.pegjs +0 -130
- package/lib/dsl-descriptor.ts +0 -241
- package/lib/index.ts +0 -5
- package/lib/nl/__test__/context-aware-prompt.test.ts +0 -372
- package/lib/nl/__test__/context-selector.test.ts +0 -27
- package/lib/nl/__test__/nl-parser-groq-transport.test.ts +0 -139
- package/lib/nl/__test__/nl-parser-openai-parity.test.ts +0 -381
- package/lib/nl/__test__/nl-parser-openai-sampling.test.ts +0 -73
- package/lib/nl/__test__/nl-parser-openai-transport.test.ts +0 -79
- package/lib/nl/__test__/nl-parser-utils.test.ts +0 -98
- package/lib/nl/__test__/nl-parser.test.ts +0 -119
- package/lib/nl/__test__/parameter-tuning.test.ts +0 -137
- package/lib/nl/__test__/semantic-parsing-experiment.test.ts +0 -260
- package/lib/nl/context-selector.ts +0 -123
- package/lib/nl/index.ts +0 -19
- package/lib/nl/llm-monitoring.test.ts +0 -136
- package/lib/nl/llm-monitoring.ts +0 -339
- package/lib/nl/nl-parser-groq.ts +0 -510
- package/lib/nl/nl-parser-utils.ts +0 -310
- package/lib/nl/nl-parser.ts +0 -616
- package/lib/nl/prompt-gen.ts +0 -607
- package/lib/nl/prompt-res.ts +0 -207
- package/lib/nl-interpreter.ts +0 -262
package/lib/nl/prompt-res.ts
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { ExampleParse } from "./prompt-gen";
|
|
2
|
-
|
|
3
|
-
export const pre_section_separator = "\n";
|
|
4
|
-
export const post_section_separator = "\n\n\n";
|
|
5
|
-
|
|
6
|
-
export const class_prequel = "// Here are all the functions";
|
|
7
|
-
|
|
8
|
-
export const array_definition =
|
|
9
|
-
"extension Array<Type> {\n" +
|
|
10
|
-
" // Find items with matching fields in an array\n" +
|
|
11
|
-
" Array<Type> matching(field: Field, value: Type);\n" +
|
|
12
|
-
"\n" +
|
|
13
|
-
" // Find items with field in an array that contains a specific value\n" +
|
|
14
|
-
" Array<Type> contains(field: Field, value: Type);\n" +
|
|
15
|
-
"\n" +
|
|
16
|
-
" // Find items with exact fields in an array\n" +
|
|
17
|
-
" Array<Type> equals(field: Field, value: Type);\n" +
|
|
18
|
-
"\n" +
|
|
19
|
-
" // Find items with the field above from (if provided) and below to (if provided).\n" +
|
|
20
|
-
" Array<Type> between(field: Field, from?: Type, to?: Type);\n" +
|
|
21
|
-
"\n" +
|
|
22
|
-
" // Sort an array based on a specific field in ascending or descending order\n" +
|
|
23
|
-
" Array<Type> sort(field: Field, ascending: bool);\n" +
|
|
24
|
-
"\n" +
|
|
25
|
-
" // Get length of an array\n" +
|
|
26
|
-
" int length();\n" +
|
|
27
|
-
"}";
|
|
28
|
-
|
|
29
|
-
export const class_separator = "\n\n";
|
|
30
|
-
|
|
31
|
-
export const example_prequel = "// Here are all the examples that we have";
|
|
32
|
-
|
|
33
|
-
export function example_pair(example: ExampleParse) {
|
|
34
|
-
return (
|
|
35
|
-
`user: ${example.user_utterance}\n` + `parsed: ${example.example_parsed}`
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export const example_separator = "\n\n";
|
|
40
|
-
|
|
41
|
-
export const accessor_parameter_rules =
|
|
42
|
-
"// Accessor parameter rules\n" +
|
|
43
|
-
"// For matching, contains, equals, between, and sort, the field parameter MUST be a dotted accessor, never a quoted string.\n" +
|
|
44
|
-
'// ✅ CORRECT: Probe.getAllProbes().contains(field: .customerName, value: "Freshmarket")\n' +
|
|
45
|
-
'// ❌ WRONG: Probe.getAllProbes().contains(field: "customerName", value: "Freshmarket")\n' +
|
|
46
|
-
"// Use nested dotted accessors for nested fields, for example .dateTime.day.\n";
|
|
47
|
-
|
|
48
|
-
export function example_parses(examples: ExampleParse[]) {
|
|
49
|
-
return examples
|
|
50
|
-
.map((example) => example_pair(example))
|
|
51
|
-
.join(example_separator);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export const user_interaction_prequel = "// New user interaction";
|
|
55
|
-
|
|
56
|
-
export function user_interaction_prompt(user_utterance: string) {
|
|
57
|
-
return `user: ${user_utterance}\n` + `parsed:`;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function agent_response_prompt(
|
|
61
|
-
user_utterance: string,
|
|
62
|
-
parsed: string,
|
|
63
|
-
result: string
|
|
64
|
-
) {
|
|
65
|
-
return (
|
|
66
|
-
`user: ${user_utterance}\n` +
|
|
67
|
-
`parsed: ${parsed}\n` +
|
|
68
|
-
`response_context: ${result}\n` +
|
|
69
|
-
`Generate STRICT JSON with keys: minimalText, fullText, type, shouldSpeak.\n` +
|
|
70
|
-
`Rules: minimalText MUST be exactly one or two words, easy to speak, and no DSL/code.\n` +
|
|
71
|
-
`Rules: minimalText should sound task/equipment-work professional (lab persona), low emotion, low cognitive load.\n` +
|
|
72
|
-
`Rules: minimalText examples: "Completed", "In progress", "Check sample", "Retry task".\n` +
|
|
73
|
-
`Rules: fullText should be informative but concise (<=240 chars).\n` +
|
|
74
|
-
`Rules: type must be one of info|error|success|warning.\n` +
|
|
75
|
-
`Rules: shouldSpeak must be true only when spoken feedback helps the user.\n` +
|
|
76
|
-
`agent_response_json:`
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export const parse_issues = `
|
|
81
|
-
// Here are the issues that need to be noticed
|
|
82
|
-
// 1. Use "Array[index]" instead of index related functions. For example, "hotels[0]" instead of "hotels.first()"
|
|
83
|
-
// 2. Use "setProperty(value) instead of "property = value". For example, "hotel.setName(123)" instead of "hotel.name = 123"
|
|
84
|
-
// 3. Use ";" between multiple function calls. For example, "hotel.setName(123); hotel.setDesc(123)"`
|
|
85
|
-
|
|
86
|
-
const exampleDeveloperClasses = `
|
|
87
|
-
// Here are all the function that we have
|
|
88
|
-
extension Array<Type> {
|
|
89
|
-
// find items with matching field in an array
|
|
90
|
-
Array<Type> matching(field: Field, value: Type);
|
|
91
|
-
|
|
92
|
-
// find items with field in an array that contains a specific value
|
|
93
|
-
Array<Type> contains(field: Field, value: Type);
|
|
94
|
-
|
|
95
|
-
// find items with exact field in an array
|
|
96
|
-
Array<Type> equals(field: Field, value: Type);
|
|
97
|
-
|
|
98
|
-
// find items with field between two values in an array
|
|
99
|
-
Array<Type> between(field: Field, from: Type, to: Type);
|
|
100
|
-
|
|
101
|
-
// sort an array based on a specific field in ascending or descending order
|
|
102
|
-
Array<Type> sort(field: Field, ascending: bool);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
class Counter {
|
|
106
|
-
string name;
|
|
107
|
-
string type;
|
|
108
|
-
int count;
|
|
109
|
-
static float Version;
|
|
110
|
-
static Counter GetCounter(name: string);
|
|
111
|
-
void increment();
|
|
112
|
-
void decrement();
|
|
113
|
-
static Counter[] All();
|
|
114
|
-
static Counter Current();
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// Here are all the examples that we have
|
|
119
|
-
user: increment
|
|
120
|
-
parsed: Counter.Current().increment()
|
|
121
|
-
|
|
122
|
-
user: what is the count
|
|
123
|
-
parsed: Counter.Current().count
|
|
124
|
-
|
|
125
|
-
user: what is the count of potato
|
|
126
|
-
parsed: Counter.GetCounter(name: "potato").count
|
|
127
|
-
|
|
128
|
-
user: increment potato counter
|
|
129
|
-
parsed: Counter.GetCounter(name: "potato").increment()
|
|
130
|
-
|
|
131
|
-
user: show me all vegetables counters
|
|
132
|
-
parsed: Counter.All().matching(field: .type, value: "vegetable")
|
|
133
|
-
`
|
|
134
|
-
|
|
135
|
-
export function parseCodePrompt(appBasicPrompt: string): string {
|
|
136
|
-
return `
|
|
137
|
-
Below are the developer class definitions, methods, and their descriptions as the comments of an example app.
|
|
138
|
-
After that, code parses from another app using ReactGenieDSL will be given.
|
|
139
|
-
A code parse is a voice command the user gives to be parsed into code that completes the requested action.
|
|
140
|
-
|
|
141
|
-
BEGIN
|
|
142
|
-
\`
|
|
143
|
-
${exampleDeveloperClasses}
|
|
144
|
-
\`
|
|
145
|
-
END
|
|
146
|
-
|
|
147
|
-
Note that all function calls have to have explicit parameter names in ReactGenieDSL.
|
|
148
|
-
|
|
149
|
-
For example:
|
|
150
|
-
\`
|
|
151
|
-
parsed: Counter.All().matching(.type, "vegetable")
|
|
152
|
-
\`
|
|
153
|
-
Is INCORRECT.
|
|
154
|
-
|
|
155
|
-
This is correct:
|
|
156
|
-
\`
|
|
157
|
-
parsed: Counter.All().matching(field: .type, value: "vegetable")
|
|
158
|
-
\`
|
|
159
|
-
|
|
160
|
-
And here is the developer classes and (optionally) code parses for this app in ReactGenieDSL:\n
|
|
161
|
-
BEGIN
|
|
162
|
-
\`
|
|
163
|
-
${appBasicPrompt}
|
|
164
|
-
\`
|
|
165
|
-
END
|
|
166
|
-
|
|
167
|
-
For code translation using \`ReactGenieDSL\`, follow these guidelines:
|
|
168
|
-
|
|
169
|
-
1. Formatting: Directly output code without code blocks. Use semicolons for separating multiple statements.
|
|
170
|
-
2. Follow declarations: Only use existing functions, do not introduce new functions.
|
|
171
|
-
3. Retrieval Over Answers: Translate user queries into code for information retrieval, not direct answers.
|
|
172
|
-
4. Contextual 'Current': Use 'Current' for items the user is directly interacting with or viewing.
|
|
173
|
-
5. Indexing: Use bracket notation for array indexing, supporting negative indices for last element.
|
|
174
|
-
6. No Math Operations: Replace direct math operations with method calls (e.g., 1.plus(1)).
|
|
175
|
-
7. Simplified Array Operations: Avoid map/lambda expressions; apply functions directly to array elements.
|
|
176
|
-
8. No Default Constructors: Use 'Create' methods for object creation; otherwise, selection from existing options.
|
|
177
|
-
9. Static vs. Non-Static Methods: Use static methods for direct class calls; retrieve instances for non-static methods.
|
|
178
|
-
10. Optional Parameters: Optional parameters are noted by \`?\` after their type, they can be omitted in function calls.
|
|
179
|
-
11. Use Setters: Avoid assignments; utilize function calls (set[Something]) for selections or changes.
|
|
180
|
-
12. Property Access: When accessing nested properties, ensure to navigate through all necessary parent properties.
|
|
181
|
-
|
|
182
|
-
**CRITICAL - Array Parameter Syntax:**
|
|
183
|
-
13. When passing array values to function parameters, you MUST wrap them in square brackets [...] even if the expression already returns an array.
|
|
184
|
-
|
|
185
|
-
✅ CORRECT: Order.current().addFoods(foods: [Order.all().matching(field: .restaurant, value: Restaurant.all()[0]).foods()])
|
|
186
|
-
❌ WRONG: Order.current().addFoods(foods: Order.all().matching(field: .restaurant, value: Restaurant.all()[0]).foods())
|
|
187
|
-
|
|
188
|
-
✅ CORRECT: someFunction(items: [array.matching(field: .name, value: "test")])
|
|
189
|
-
❌ WRONG: someFunction(items: array.matching(field: .name, value: "test"))
|
|
190
|
-
|
|
191
|
-
Even though the expression returns an array type, the DSL syntax requires explicit brackets for array parameters.
|
|
192
|
-
|
|
193
|
-
**CRITICAL - Accessor Parameter Syntax:**
|
|
194
|
-
14. For matching, contains, equals, between, and sort, the \`field\` parameter MUST be a dotted accessor, never a quoted string literal.
|
|
195
|
-
|
|
196
|
-
✅ CORRECT: Probe.getAllProbes().contains(field: .customerName, value: "Freshmarket")
|
|
197
|
-
❌ WRONG: Probe.getAllProbes().contains(field: "customerName", value: "Freshmarket")
|
|
198
|
-
|
|
199
|
-
✅ CORRECT: Probe.getAllProbes().sort(field: .receivedAt, ascending: false)
|
|
200
|
-
❌ WRONG: Probe.getAllProbes().sort(field: "receivedAt", ascending: false)
|
|
201
|
-
|
|
202
|
-
For nested fields, keep the full dotted path, for example \`.dateTime.day\`.
|
|
203
|
-
|
|
204
|
-
New user interaction (think carefully)
|
|
205
|
-
|
|
206
|
-
`;
|
|
207
|
-
}
|
package/lib/nl-interpreter.ts
DELETED
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
import { PromptGen, SamplingParams } from "./nl";
|
|
2
|
-
import { ClassDescriptor, GenieObject } from "./dsl-descriptor";
|
|
3
|
-
import { NlParser, NlParserGroq } from "./nl";
|
|
4
|
-
import { DslInterpreter } from "./dsl";
|
|
5
|
-
import {
|
|
6
|
-
AgentResponsePayload,
|
|
7
|
-
ContextAwareDescriptorPromptGen,
|
|
8
|
-
ExampleParse,
|
|
9
|
-
PromptInteractionRecorder,
|
|
10
|
-
PromptRuntimeContextSetter,
|
|
11
|
-
RuntimeUiContext,
|
|
12
|
-
} from "./nl/prompt-gen";
|
|
13
|
-
|
|
14
|
-
export type NlParserProvider = "groq" | "openai";
|
|
15
|
-
|
|
16
|
-
export interface NlInterpreterProviderSettings {
|
|
17
|
-
baseUrl?: string;
|
|
18
|
-
model?: string;
|
|
19
|
-
samplingParams?: SamplingParams;
|
|
20
|
-
statefulValidationRetry?: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface NlInterpreterParserConfig {
|
|
24
|
-
provider?: NlParserProvider;
|
|
25
|
-
groq?: NlInterpreterProviderSettings;
|
|
26
|
-
openai?: NlInterpreterProviderSettings;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface NlInterpreterMonitoringConfig {
|
|
30
|
-
langsmithApiKey?: string;
|
|
31
|
-
langsmithProject?: string;
|
|
32
|
-
langsmithEndpoint?: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface NlInterpreterOptions {
|
|
36
|
-
parser?: NlInterpreterParserConfig;
|
|
37
|
-
monitoring?: NlInterpreterMonitoringConfig;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const DEFAULT_GROQ_BASE_URL = "https://api.groq.com/openai/v1";
|
|
41
|
-
const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
|
|
42
|
-
const PROVIDER_ENV_KEY = "GENIE_PARSER_PROVIDER";
|
|
43
|
-
|
|
44
|
-
function normalizeBaseUrl(baseUrl: string): string {
|
|
45
|
-
return baseUrl.trim().replace(/\/+$/, "");
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function stripChatCompletionsSuffix(baseUrl: string): string {
|
|
49
|
-
if (!baseUrl.endsWith("/chat/completions")) {
|
|
50
|
-
return baseUrl;
|
|
51
|
-
}
|
|
52
|
-
return baseUrl.slice(0, -"/chat/completions".length);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function isDirectOpenAIBaseUrl(baseUrl: string): boolean {
|
|
56
|
-
try {
|
|
57
|
-
const url = new URL(baseUrl);
|
|
58
|
-
return url.hostname === "api.openai.com";
|
|
59
|
-
} catch {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function normalizeProviderBaseUrl(
|
|
65
|
-
provider: NlParserProvider,
|
|
66
|
-
baseUrl?: string
|
|
67
|
-
): string {
|
|
68
|
-
const fallbackBaseUrl =
|
|
69
|
-
provider === "openai" ? DEFAULT_OPENAI_BASE_URL : DEFAULT_GROQ_BASE_URL;
|
|
70
|
-
|
|
71
|
-
if (!baseUrl || baseUrl.trim().length === 0) {
|
|
72
|
-
return fallbackBaseUrl;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const normalizedBaseUrl = stripChatCompletionsSuffix(normalizeBaseUrl(baseUrl));
|
|
76
|
-
|
|
77
|
-
if (
|
|
78
|
-
normalizedBaseUrl.endsWith("/openai/v1") ||
|
|
79
|
-
normalizedBaseUrl.endsWith("/v1")
|
|
80
|
-
) {
|
|
81
|
-
return normalizedBaseUrl;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (provider === "openai" && isDirectOpenAIBaseUrl(normalizedBaseUrl)) {
|
|
85
|
-
return `${normalizedBaseUrl}/v1`;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return `${normalizedBaseUrl}/openai/v1`;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function resolveParserProvider(
|
|
92
|
-
parserConfig?: NlInterpreterParserConfig
|
|
93
|
-
): NlParserProvider {
|
|
94
|
-
if (parserConfig?.provider === "openai" || parserConfig?.provider === "groq") {
|
|
95
|
-
return parserConfig.provider;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const envProvider = process.env[PROVIDER_ENV_KEY]?.trim().toLowerCase();
|
|
99
|
-
if (envProvider === "openai" || envProvider === "groq") {
|
|
100
|
-
return envProvider;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return "groq";
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function requireOpenAIModel(model?: string): string {
|
|
107
|
-
const trimmed = model?.trim();
|
|
108
|
-
if (!trimmed) {
|
|
109
|
-
throw new Error(
|
|
110
|
-
"OpenAI parser requires parser.openai.model / semanticModel / SEMANTIC_MODEL configuration."
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
return trimmed;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export class NlInterpreter {
|
|
117
|
-
public nlParser: NlParser | NlParserGroq;
|
|
118
|
-
public dslInterpreter: DslInterpreter;
|
|
119
|
-
private dslValidator: DslInterpreter;
|
|
120
|
-
|
|
121
|
-
constructor(
|
|
122
|
-
private descriptions: ClassDescriptor<GenieObject>[],
|
|
123
|
-
private apiKey: string,
|
|
124
|
-
private prompt?: PromptGen,
|
|
125
|
-
private examples?: ExampleParse[],
|
|
126
|
-
private extraPrompt?: string,
|
|
127
|
-
private options: NlInterpreterOptions = {}
|
|
128
|
-
) {
|
|
129
|
-
if (this.prompt === undefined) {
|
|
130
|
-
console.assert(this.examples !== undefined);
|
|
131
|
-
this.prompt = new ContextAwareDescriptorPromptGen(
|
|
132
|
-
this.descriptions,
|
|
133
|
-
this.examples!,
|
|
134
|
-
extraPrompt
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const parserConfig = this.options.parser;
|
|
139
|
-
const monitoringConfig = this.options.monitoring;
|
|
140
|
-
const provider = resolveParserProvider(parserConfig);
|
|
141
|
-
|
|
142
|
-
this.dslInterpreter = new DslInterpreter([...descriptions]);
|
|
143
|
-
this.dslValidator = new DslInterpreter([...descriptions], true);
|
|
144
|
-
|
|
145
|
-
const validateCommand = async (command: string) => {
|
|
146
|
-
await this.dslValidator.interpret(command);
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
if (provider === "openai") {
|
|
150
|
-
const openAIConfig = parserConfig?.openai;
|
|
151
|
-
this.nlParser = new NlParser(
|
|
152
|
-
this.prompt,
|
|
153
|
-
apiKey,
|
|
154
|
-
normalizeProviderBaseUrl("openai", openAIConfig?.baseUrl),
|
|
155
|
-
requireOpenAIModel(openAIConfig?.model),
|
|
156
|
-
openAIConfig?.samplingParams,
|
|
157
|
-
monitoringConfig?.langsmithApiKey,
|
|
158
|
-
monitoringConfig?.langsmithProject,
|
|
159
|
-
monitoringConfig?.langsmithEndpoint,
|
|
160
|
-
validateCommand,
|
|
161
|
-
{
|
|
162
|
-
statefulValidationRetry: !!openAIConfig?.statefulValidationRetry,
|
|
163
|
-
}
|
|
164
|
-
);
|
|
165
|
-
} else {
|
|
166
|
-
const groqConfig = parserConfig?.groq;
|
|
167
|
-
const resolvedGroqModel =
|
|
168
|
-
groqConfig?.model ||
|
|
169
|
-
process.env.SEMANTIC_MODEL ||
|
|
170
|
-
"llama-3.3-70b-versatile";
|
|
171
|
-
this.nlParser = new NlParserGroq(
|
|
172
|
-
this.prompt,
|
|
173
|
-
apiKey,
|
|
174
|
-
resolvedGroqModel,
|
|
175
|
-
groqConfig?.samplingParams,
|
|
176
|
-
normalizeProviderBaseUrl("groq", groqConfig?.baseUrl),
|
|
177
|
-
monitoringConfig?.langsmithApiKey,
|
|
178
|
-
monitoringConfig?.langsmithProject,
|
|
179
|
-
monitoringConfig?.langsmithEndpoint,
|
|
180
|
-
validateCommand
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
private recordInteraction(record: {
|
|
186
|
-
utterance: string;
|
|
187
|
-
parsed?: string | null;
|
|
188
|
-
success: boolean;
|
|
189
|
-
resultSummary?: string;
|
|
190
|
-
}) {
|
|
191
|
-
const recorder = this.prompt as unknown as PromptInteractionRecorder;
|
|
192
|
-
if (typeof recorder?.recordInteraction === "function") {
|
|
193
|
-
recorder.recordInteraction(record);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
public recordTurn(record: {
|
|
198
|
-
utterance: string;
|
|
199
|
-
parsed?: string | null;
|
|
200
|
-
success: boolean;
|
|
201
|
-
resultSummary?: string;
|
|
202
|
-
}): void {
|
|
203
|
-
this.recordInteraction(record);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
setRuntimeContext(context: RuntimeUiContext | null): void {
|
|
207
|
-
const runtimeContextSetter = this.prompt as unknown as PromptRuntimeContextSetter;
|
|
208
|
-
if (typeof runtimeContextSetter?.setRuntimeContext === "function") {
|
|
209
|
-
runtimeContextSetter.setRuntimeContext(context);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
async interpret(nl: string): Promise<GenieObject | null> {
|
|
214
|
-
let command: string | null = null;
|
|
215
|
-
try {
|
|
216
|
-
command = await this.nlParser.parse(nl);
|
|
217
|
-
} catch (error) {
|
|
218
|
-
this.recordInteraction({
|
|
219
|
-
utterance: nl,
|
|
220
|
-
success: false,
|
|
221
|
-
resultSummary: `parse_error:${error instanceof Error ? error.message : String(error)}`,
|
|
222
|
-
});
|
|
223
|
-
throw error;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
if (command === null) {
|
|
227
|
-
this.recordInteraction({
|
|
228
|
-
utterance: nl,
|
|
229
|
-
success: false,
|
|
230
|
-
resultSummary: "parse_empty",
|
|
231
|
-
});
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
try {
|
|
236
|
-
const result = await this.dslInterpreter.interpret(command);
|
|
237
|
-
this.recordInteraction({
|
|
238
|
-
utterance: nl,
|
|
239
|
-
parsed: command,
|
|
240
|
-
success: true,
|
|
241
|
-
resultSummary: "execute_ok",
|
|
242
|
-
});
|
|
243
|
-
return result;
|
|
244
|
-
} catch (error) {
|
|
245
|
-
this.recordInteraction({
|
|
246
|
-
utterance: nl,
|
|
247
|
-
parsed: command,
|
|
248
|
-
success: false,
|
|
249
|
-
resultSummary: `execute_error:${error instanceof Error ? error.message : String(error)}`,
|
|
250
|
-
});
|
|
251
|
-
throw error;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
async respond(
|
|
256
|
-
nl: string,
|
|
257
|
-
parsed: string,
|
|
258
|
-
result: string
|
|
259
|
-
): Promise<AgentResponsePayload | null> {
|
|
260
|
-
return await this.nlParser.respond(nl, parsed, result);
|
|
261
|
-
}
|
|
262
|
-
}
|