recursive-llm-ts 4.0.0 → 4.0.1

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/bin/rlm-go CHANGED
Binary file
@@ -37,22 +37,28 @@ func (r *RLM) structuredCompletionDirect(query string, context string, config *S
37
37
 
38
38
  // Build comprehensive prompt with context and schema
39
39
  constraints := generateSchemaConstraints(config.Schema)
40
+ requiredFieldsHint := ""
41
+ if config.Schema.Type == "object" && len(config.Schema.Required) > 0 {
42
+ requiredFieldsHint = fmt.Sprintf("\nREQUIRED FIELDS (you MUST include these): %s\n", strings.Join(config.Schema.Required, ", "))
43
+ }
44
+
40
45
  prompt := fmt.Sprintf(
41
46
  "You are a data extraction assistant. Extract information from the context and return it as JSON.\n\n"+
42
47
  "Context:\n%s\n\n"+
43
48
  "Task: %s\n\n"+
44
- "Required JSON Schema:\n%s\n\n"+
49
+ "Required JSON Schema:\n%s%s\n\n"+
45
50
  "%s"+
46
51
  "CRITICAL INSTRUCTIONS:\n"+
47
52
  "1. Return ONLY valid JSON - no explanations, no markdown, no code blocks\n"+
48
53
  "2. The JSON must match the schema EXACTLY\n"+
49
- "3. Include ALL required fields\n"+
54
+ "3. Include ALL required fields (see list above)\n"+
50
55
  "4. Use correct data types (strings in quotes, numbers without quotes, arrays in [], objects in {})\n"+
51
56
  "5. For arrays, return actual JSON arrays [] not objects\n"+
52
57
  "6. For enum fields, use ONLY the EXACT values listed - do not paraphrase or substitute\n"+
53
- "7. Start your response directly with { or [ depending on the schema\n\n"+
58
+ "7. For nested objects, ensure ALL required fields within those objects are included\n"+
59
+ "8. Start your response directly with { or [ depending on the schema\n\n"+
54
60
  "JSON Response:",
55
- context, query, string(schemaJSON), constraints,
61
+ context, query, string(schemaJSON), requiredFieldsHint, constraints,
56
62
  )
57
63
 
58
64
  var lastErr error
@@ -192,7 +198,7 @@ func generateSchemaConstraints(schema *JSONSchema) string {
192
198
  if schema.Type == "object" && schema.Properties != nil {
193
199
  for fieldName, fieldSchema := range schema.Properties {
194
200
  if fieldSchema.Type == "number" {
195
- if strings.Contains(strings.ToLower(fieldName), "sentiment") {
201
+ if strings.Contains(strings.ToLower(fieldName), "sentiment") || strings.Contains(strings.ToLower(fieldName), "score") {
196
202
  constraints = append(constraints, fmt.Sprintf("- %s must be a number between 1 and 5 (inclusive)", fieldName))
197
203
  }
198
204
  }
@@ -202,6 +208,10 @@ func generateSchemaConstraints(schema *JSONSchema) string {
202
208
  if fieldSchema.Type == "array" {
203
209
  constraints = append(constraints, fmt.Sprintf("- %s must be a JSON array []", fieldName))
204
210
  }
211
+ // Add constraint for nested objects with required fields
212
+ if fieldSchema.Type == "object" && len(fieldSchema.Required) > 0 {
213
+ constraints = append(constraints, fmt.Sprintf("- %s must be an object with these REQUIRED fields: %s", fieldName, strings.Join(fieldSchema.Required, ", ")))
214
+ }
205
215
  }
206
216
  }
207
217
 
@@ -228,7 +238,7 @@ func generateSchemaConstraints(schema *JSONSchema) string {
228
238
  // generateFieldQuery creates a focused query for a specific field
229
239
  func generateFieldQuery(fieldName string, schema *JSONSchema) string {
230
240
  fieldQueries := map[string]string{
231
- "sentiment": "Analyze the overall sentiment of this conversation. Provide a sentiment score from 1-5 and a detailed explanation.",
241
+ "sentiment": "Analyze the overall sentiment of this conversation. Return a JSON object with: score (integer 1-5), confidence (number 0-1), and optional reasoning (string).",
232
242
  "sentimentValue": "What is the overall sentiment score (1-5) of this conversation?",
233
243
  "sentimentExplanation": "Explain in 2-3 sentences why the conversation has this sentiment score.",
234
244
  "phrases": "Extract key phrases that significantly impacted the sentiment, excluding neutral (3-value) phrases. For each phrase, include the sentiment value and the phrase itself (1 sentence).",
@@ -239,6 +249,12 @@ func generateFieldQuery(fieldName string, schema *JSONSchema) string {
239
249
  return query
240
250
  }
241
251
 
252
+ // For object types, provide more detailed instructions about required fields
253
+ if schema.Type == "object" && len(schema.Required) > 0 {
254
+ return fmt.Sprintf("Extract the %s from the conversation. Return a JSON object with these required fields: %s.",
255
+ fieldName, strings.Join(schema.Required, ", "))
256
+ }
257
+
242
258
  return fmt.Sprintf("Extract the %s from the conversation.", fieldName)
243
259
  }
244
260
 
@@ -264,11 +280,48 @@ func parseAndValidateJSON(result string, schema *JSONSchema) (map[string]interfa
264
280
  if parseErr == nil {
265
281
  // Check if it's a map (LLM wrapped the value in an object)
266
282
  if valueMap, ok := value.(map[string]interface{}); ok {
267
- // If it's a single-key object, extract the value
268
- if len(valueMap) == 1 {
283
+ // Try to unwrap based on expected type
284
+ switch schema.Type {
285
+ case "array":
286
+ // Look for any array value in the map
287
+ for _, v := range valueMap {
288
+ if arr, ok := v.([]interface{}); ok {
289
+ value = arr
290
+ break
291
+ }
292
+ }
293
+ case "string":
294
+ // Look for any string value in the map
295
+ for _, v := range valueMap {
296
+ if str, ok := v.(string); ok {
297
+ value = str
298
+ break
299
+ }
300
+ }
301
+ case "number":
302
+ // Look for any number value in the map
269
303
  for _, v := range valueMap {
270
- value = v
271
- break
304
+ switch v.(type) {
305
+ case float64, float32, int, int32, int64:
306
+ value = v
307
+ break
308
+ }
309
+ }
310
+ case "boolean":
311
+ // Look for any boolean value in the map
312
+ for _, v := range valueMap {
313
+ if b, ok := v.(bool); ok {
314
+ value = b
315
+ break
316
+ }
317
+ }
318
+ default:
319
+ // For other types, extract single-key value
320
+ if len(valueMap) == 1 {
321
+ for _, v := range valueMap {
322
+ value = v
323
+ break
324
+ }
272
325
  }
273
326
  }
274
327
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "recursive-llm-ts",
3
- "version": "4.0.0",
3
+ "version": "4.0.1",
4
4
  "description": "TypeScript bridge for recursive-llm: Recursive Language Models for unbounded context processing with structured outputs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",