@saltcorn/large-language-model 0.3.6 → 0.4.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.
@@ -0,0 +1,150 @@
1
+ const Workflow = require("@saltcorn/data/models/workflow");
2
+ const Form = require("@saltcorn/data/models/form");
3
+ const FieldRepeat = require("@saltcorn/data/models/fieldrepeat");
4
+ const Field = require("@saltcorn/data/models/field");
5
+ const Table = require("@saltcorn/data/models/table");
6
+ const { getState } = require("@saltcorn/data/db/state");
7
+ const { interpolate } = require("@saltcorn/data/utils");
8
+ const { getCompletion, getEmbedding } = require("./generate");
9
+ const { eval_expression } = require("@saltcorn/data/models/expression");
10
+
11
+ const noSpaces = (s) => s.replaceAll(" ", "");
12
+ module.exports = (config) => ({
13
+ description: "Use LLM function call to insert rows in tables",
14
+ requireRow: true,
15
+ configFields: async ({ table }) => {
16
+ const tables = await Table.find();
17
+ return [
18
+ {
19
+ name: "prompt_template",
20
+ label: "Prompt",
21
+ type: "String",
22
+ fieldview: "textarea",
23
+ sublabel: `Use interpolations {{ }} to access variables in ${table.name} table.`,
24
+ },
25
+ {
26
+ name: "function_name",
27
+ label: "Function name",
28
+ type: "String",
29
+ },
30
+ {
31
+ name: "function_description",
32
+ label: "Function description",
33
+ sublabel: "Describe what you are trying to achieve in general terms",
34
+ type: "String",
35
+ },
36
+ new FieldRepeat({
37
+ name: "columns",
38
+ fields: [
39
+ {
40
+ name: "target_table",
41
+ label: "Target table",
42
+ type: "String",
43
+ required: true,
44
+ attributes: { options: tables.map((t) => t.name) },
45
+ },
46
+ {
47
+ label: "Fixed values",
48
+ name: "fixed_values",
49
+ type: "String",
50
+ fieldview: "textarea",
51
+ },
52
+ {
53
+ name: "cardinality",
54
+ label: "Cardinality",
55
+ type: "String",
56
+ required: true,
57
+ attributes: {
58
+ options: ["One", /*"Zero or one",*/ "Zero to many"],
59
+ },
60
+ },
61
+ ],
62
+ }),
63
+ ];
64
+ },
65
+ run: async ({
66
+ row,
67
+ table,
68
+ configuration: {
69
+ prompt_template,
70
+ columns,
71
+ function_description,
72
+ function_name,
73
+ },
74
+ user,
75
+ }) => {
76
+ const prompt = interpolate(prompt_template, row, user);
77
+ let args = {};
78
+ const json_type = (ty) => {
79
+ if (ty?.js_type) return ty?.js_type;
80
+ };
81
+
82
+ for (const col of columns) {
83
+ const target_table = Table.findOne({ name: col.target_table });
84
+ const tableArgs = {};
85
+ const fixed = eval_expression(
86
+ col.fixed_values,
87
+ row,
88
+ user,
89
+ "llm_function_call fixed values"
90
+ );
91
+ for (const field of target_table.fields) {
92
+ if (field.primary_key) continue;
93
+ if (typeof fixed[field.name] !== "undefined") continue;
94
+ tableArgs[field.name] = {
95
+ type: json_type(field.type),
96
+ description: field.description,
97
+ };
98
+ }
99
+ const argObj = { type: "object", properties: tableArgs };
100
+ args[noSpaces(target_table.name)] =
101
+ col.cardinality == "One" ? argObj : { type: "array", items: argObj };
102
+ }
103
+ if (columns.length === 1) {
104
+ //args = args[Object]
105
+ }
106
+ const expert_function = {
107
+ type: "function",
108
+ function: {
109
+ name: function_name,
110
+ description: function_description,
111
+ parameters: {
112
+ type: "object",
113
+ properties: args,
114
+ },
115
+ },
116
+ };
117
+ const toolargs = {
118
+ tools: [expert_function],
119
+ tool_choice: { type: "function", function: { name: function_name } },
120
+ };
121
+ //console.log(JSON.stringify(expert_function, null, 2));
122
+ const compl = await getCompletion(config, { prompt, ...toolargs });
123
+
124
+ const response = JSON.parse(compl.tool_calls[0].function.arguments);
125
+ //console.log("response: ", JSON.stringify(response, null, 2));
126
+ for (const col of columns) {
127
+ const target_table = Table.findOne({ name: col.target_table });
128
+ const fixed = eval_expression(
129
+ col.fixed_values,
130
+ row,
131
+ user,
132
+ "llm_function_call fixed values"
133
+ );
134
+
135
+ if (col.cardinality == "One") {
136
+ const row = {
137
+ ...(response[noSpaces(target_table.name)] || {}),
138
+ ...fixed,
139
+ };
140
+ await target_table.insertRow(row, user);
141
+ } else {
142
+ for (const resp of response[noSpaces(target_table.name)] || []) {
143
+ const row = { ...resp, ...fixed };
144
+ await target_table.insertRow(row, user);
145
+ }
146
+ }
147
+ }
148
+ return {};
149
+ },
150
+ });
package/generate.js CHANGED
@@ -109,7 +109,7 @@ const getCompletionOpenAICompatible = async (
109
109
  if (bearer) headers.Authorization = "Bearer " + bearer;
110
110
  const body = {
111
111
  //prompt: "How are you?",
112
- model,
112
+ model: rest.model || model,
113
113
  messages: [
114
114
  {
115
115
  role: "system",
@@ -121,6 +121,7 @@ const getCompletionOpenAICompatible = async (
121
121
  temperature: temperature || 0.7,
122
122
  ...rest,
123
123
  };
124
+ if (debugResult) console.log("OpenAI request", JSON.stringify(body, null, 2));
124
125
  const rawResponse = await fetch(chatCompleteEndpoint, {
125
126
  method: "POST",
126
127
  headers,
package/index.js CHANGED
@@ -58,10 +58,14 @@ const configuration_workflow = () =>
58
58
  options: [
59
59
  "gpt-3.5-turbo",
60
60
  "gpt-3.5-turbo-16k",
61
+ "gpt-3.5-turbo-1106",
62
+ "gpt-3.5-turbo-0125",
61
63
  "gpt-4",
62
64
  "gpt-4-32k",
63
65
  "gpt-4-turbo-preview",
64
66
  "gpt-4-1106-preview",
67
+ "gpt-4-0125-preview",
68
+ "gpt-4-turbo",
65
69
  ],
66
70
  },
67
71
  },
@@ -136,4 +140,7 @@ module.exports = {
136
140
  configuration_workflow,
137
141
  functions,
138
142
  modelpatterns: require("./model.js"),
143
+ actions: (config) => ({
144
+ llm_function_call: require("./function-insert-action.js")(config),
145
+ }),
139
146
  };
package/model.js CHANGED
@@ -35,8 +35,14 @@ const configuration_workflow = (config) => (req) =>
35
35
  models = [
36
36
  "gpt-3.5-turbo",
37
37
  "gpt-3.5-turbo-16k",
38
+ "gpt-3.5-turbo-1106",
39
+ "gpt-3.5-turbo-0125",
38
40
  "gpt-4",
39
41
  "gpt-4-32k",
42
+ "gpt-4-turbo-preview",
43
+ "gpt-4-1106-preview",
44
+ "gpt-4-0125-preview",
45
+ "gpt-4-turbo",
40
46
  ];
41
47
  }
42
48
  return new Form({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/large-language-model",
3
- "version": "0.3.6",
3
+ "version": "0.4.0",
4
4
  "description": "Large language models and functionality for Saltcorn",
5
5
  "main": "index.js",
6
6
  "dependencies": {