-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add template source adapters for JSON and Markdown files
- Introduced a base `TemplateSourceAdapter` class for handling template file operations, including methods for reading and writing files. - Implemented `FileJsonTemplateSourceAdapter` for JSON files, providing functionality to import and write JSON data. - Created `MarkdownTemplateAdapter` to read and parse Markdown files, extracting headings and content into a structured format. - Added a specialized `ToolJsonTemplateAdapter` for handling `.tool.json` files, including methods for importing and exporting tool definitions. - Removed the old `_adapter.js` file to streamline the adapter structure. - Updated the `lookup` template to reflect new data structures and added corresponding Markdown and JSON representations.
- Loading branch information
Brian Joseph Petro
committed
Jan 8, 2025
1 parent
98b7821
commit 4f4b093
Showing
8 changed files
with
307 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/** | ||
* @class TemplateSourceAdapter | ||
* @description Base adapter class for handling template source file operations. | ||
* Each subclass should override `import()` to parse or transform the file into `this.item.data`. | ||
*/ | ||
export class TemplateSourceAdapter { | ||
/** | ||
* @constructor | ||
* @param {Object} item - The template item this adapter is associated with. | ||
*/ | ||
constructor(item) { | ||
this.item = item; | ||
} | ||
|
||
/** | ||
* Helper to read the raw file content. Usually used internally by `import()`. | ||
* @async | ||
* @returns {Promise<string>} The file contents. | ||
*/ | ||
async read() { | ||
return await this.fs.read(this.file_path); | ||
} | ||
|
||
/** | ||
* Helper to write raw data back to the file system. | ||
* @async | ||
* @param {string|Object} data - The data to write to the file | ||
* @returns {Promise<void>} Resolves when write completes | ||
*/ | ||
async write(data) { | ||
return await this.fs.write(this.file_path, data); | ||
} | ||
|
||
/** | ||
* The main method each adapter should override to parse or transform the file | ||
* and store the result in `this.item.data`. | ||
* @async | ||
* @returns {Promise<any>} The parsed or processed result | ||
*/ | ||
async import() { | ||
throw new Error('import() not implemented by subclass'); | ||
} | ||
|
||
/** | ||
* For convenience, references to the file path and FS from the item. | ||
*/ | ||
get fs() { | ||
return this.item.collection.fs; | ||
} | ||
get file_path() { | ||
return this.item.path; // or logic to unify extension if needed | ||
} | ||
} | ||
|
||
export default { | ||
item: TemplateSourceAdapter, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { TemplateSourceAdapter } from './_adapter.js'; | ||
import { parse_blocks } from 'smart-blocks/parsers/markdown.js'; | ||
|
||
/** | ||
* @class MarkdownTemplateAdapter | ||
* @extends TemplateSourceAdapter | ||
* @description | ||
* Adapter that reads a Markdown file, uses `parse_blocks` to find headings and content, | ||
* and populates `this.item.data` accordingly. | ||
*/ | ||
export class MarkdownTemplateAdapter extends TemplateSourceAdapter { | ||
/** @type {string} The file extension this adapter targets. */ | ||
static extension = 'md'; | ||
extension = 'md'; | ||
|
||
/** | ||
* @async | ||
* @method import | ||
* @description | ||
* 1) Read the markdown content | ||
* 2) Parse via `parse_blocks` | ||
* 3) Store heading => content mapping in `this.item.data.headings` | ||
* @returns {Promise<Object>} The headings data object | ||
*/ | ||
async import() { | ||
const markdownContent = await this.read(); | ||
const blocksMap = parse_blocks(markdownContent); | ||
|
||
const headingsData = {}; | ||
for (const [blockKey, [start, end]] of Object.entries(blocksMap)) { | ||
const lines = markdownContent.split('\n').slice(start - 1, end); | ||
const blockText = lines.join('\n').trim(); | ||
if (!blockText) continue; | ||
|
||
// Clean the heading name from blockKey | ||
let headingName = blockKey.replace(/^#+/, '').trim() || '(root)'; | ||
headingsData[headingName] = blockText; | ||
} | ||
|
||
// Store in item.data or merge if needed | ||
if (!this.item.data.headings) this.item.data.headings = {}; | ||
Object.assign(this.item.data.headings, headingsData); | ||
|
||
return headingsData; | ||
} | ||
} | ||
|
||
export default { | ||
item: MarkdownTemplateAdapter | ||
}; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
// File: smart-templates-2/adapters/tool_json.js | ||
|
||
import { TemplateSourceAdapter } from "./_adapter.js"; | ||
|
||
/** | ||
* @class ToolJsonTemplateAdapter | ||
* @extends TemplateSourceAdapter | ||
* @description Adapter for specialized `.tool.json` files containing tool definitions | ||
* (OpenAI function format) plus optional fields like var_prompts, prompt, opts, output, etc. | ||
*/ | ||
export class ToolJsonTemplateAdapter extends TemplateSourceAdapter { | ||
static extension = 'tool.json'; | ||
extension = 'tool.json'; | ||
|
||
/** | ||
* @async | ||
* @method import | ||
* @description Reads the `.tool.json` file and converts it to the standard template format | ||
* @returns {Promise<Object>} The parsed and converted template data | ||
*/ | ||
async import() { | ||
const raw = await this.read(); | ||
const parsed = JSON.parse(raw); | ||
|
||
// Initialize data structure if needed | ||
if (!this.item.data.var_prompts) this.item.data.var_prompts = {}; | ||
if (!this.item.data.opts) this.item.data.opts = {}; | ||
|
||
// Handle tool function parameters conversion | ||
if (parsed.tool?.function?.parameters?.properties) { | ||
const props = parsed.tool.function.parameters.properties; | ||
|
||
// Convert nested object parameters to multiple_output format | ||
for (const [key, value] of Object.entries(props)) { | ||
if (value.type === 'object' && value.properties) { | ||
// Store the original description in var_prompts | ||
if (value.description) { | ||
this.item.data.var_prompts[key] = value.description; | ||
} | ||
|
||
// Set up multiple_output options | ||
if (!this.item.data.opts.multiple_output) { | ||
this.item.data.opts.multiple_output = []; | ||
} | ||
if (!this.item.data.opts.multiple_output.includes(key)) { | ||
this.item.data.opts.multiple_output.push(key); | ||
} | ||
|
||
// Count the number of required outputs | ||
const numOutputs = Object.keys(value.properties).length; | ||
this.item.data.opts.multiple_output_count = numOutputs; | ||
|
||
} | ||
} | ||
} | ||
|
||
// Copy over the function description as the prompt | ||
if (parsed.tool?.function?.description) { | ||
this.item.data.prompt = parsed.tool.function.description; | ||
} | ||
|
||
// Copy the name | ||
if (parsed.name) { | ||
this.item.data.name = parsed.name; | ||
} | ||
|
||
return this.item.data; | ||
} | ||
|
||
/** | ||
* @async | ||
* @method export | ||
* @description Converts the standard template format back to tool.json format | ||
* @returns {Promise<string>} The stringified tool.json content | ||
*/ | ||
async export() { | ||
const data = this.item.data; | ||
const toolJson = { | ||
name: data.name, | ||
tool: { | ||
type: "function", | ||
function: { | ||
name: data.name, | ||
description: data.prompt, | ||
parameters: { | ||
type: "object", | ||
properties: {}, | ||
required: [] | ||
} | ||
} | ||
}, | ||
output: data.output || {}, | ||
opts: { ...data.opts } | ||
}; | ||
|
||
// Convert multiple_output format back to nested object parameters | ||
if (data.opts?.multiple_output) { | ||
for (const key of data.opts.multiple_output) { | ||
const numOutputs = data.opts.multiple_output_count || 3; | ||
const properties = {}; | ||
|
||
// Create numbered properties | ||
for (let i = 1; i <= numOutputs; i++) { | ||
properties[i] = { type: "string" }; | ||
} | ||
|
||
toolJson.tool.function.parameters.properties[key] = { | ||
type: "object", | ||
description: data.var_prompts[key], | ||
properties: properties, | ||
required: Object.keys(properties) | ||
}; | ||
|
||
toolJson.tool.function.parameters.required.push(key); | ||
} | ||
} | ||
|
||
return JSON.stringify(toolJson, null, 2); | ||
} | ||
} | ||
|
||
export default { | ||
item: ToolJsonTemplateAdapter | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,11 @@ | ||
{ | ||
"opts": { | ||
"lookup_hypotheticals_map": { | ||
"1": "hypotheticals.1", | ||
"2": "hypotheticals.2", | ||
"3": "hypotheticals.3" | ||
} | ||
"multiple_output": ["hypothetical"], | ||
"multiple_output_count": 3 | ||
}, | ||
"name": "lookup", | ||
"tool": { | ||
"type": "function", | ||
"function": { | ||
"name": "lookup", | ||
"description": "Performs a semantic search of the user's data. Use this function to respond to queries like 'Based on my notes...' or any other request that requires surfacing relevant content.", | ||
"parameters": { | ||
"type": "object", | ||
"properties": { | ||
"hypotheticals": { | ||
"type": "object", | ||
"description": "Short hypothetical notes predicted to be semantically similar to the notes necessary to fulfill the user's request. Provide at least three hypotheticals per request. The hypothetical notes may contain paragraphs, lists, or checklists in markdown format. Each hypothetical note should begin with breadcrumbs indicating the anticipated folder(s), file name, and relevant headings separated by ' > ' (no slashes). Example: PARENT FOLDER NAME > CHILD FOLDER NAME > FILE NAME > HEADING 1 > HEADING 2 > HEADING 3: HYPOTHETICAL NOTE CONTENTS.", | ||
"properties": { | ||
"1": { | ||
"type": "string" | ||
}, | ||
"2": { | ||
"type": "string" | ||
}, | ||
"3": { | ||
"type": "string" | ||
} | ||
}, | ||
"required": ["1", "2", "3"] | ||
} | ||
}, | ||
"required": ["hypotheticals"] | ||
} | ||
} | ||
}, | ||
"output": {} | ||
"prompt": "Performs a semantic search of the user's data. Use this function to respond to queries like 'Based on my notes...' or any other request that requires surfacing relevant content.", | ||
"var_prompts": { | ||
"hypothetical": "Short hypothetical notes predicted to be semantically similar to the notes necessary to fulfill the user's request. Provide at least three hypotheticals per request. The hypothetical notes may contain paragraphs, lists, or checklists in markdown format. Each hypothetical note should begin with breadcrumbs indicating the anticipated folder(s), file name, and relevant headings separated by ' > ' (no slashes). Example: PARENT FOLDER NAME > CHILD FOLDER NAME > FILE NAME > HEADING 1 > HEADING 2 > HEADING 3: HYPOTHETICAL NOTE CONTENTS." | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--- | ||
name: lookup | ||
multiple_output: | ||
- hypothetical | ||
multiple_output_count: 3 | ||
--- | ||
Performs a semantic search of the user's data. Use this function to respond to queries like 'Based on my notes...' or any other request that requires surfacing relevant content. | ||
|
||
# hypothetical | ||
Short hypothetical notes predicted to be semantically similar to the notes necessary to fulfill the user's request. Provide at least three hypotheticals per request. The hypothetical notes may contain paragraphs, lists, or checklists in markdown format. Each hypothetical note should begin with breadcrumbs indicating the anticipated folder(s), file name, and relevant headings separated by ' > ' (no slashes). Example: PARENT FOLDER NAME > CHILD FOLDER NAME > FILE NAME > HEADING 1 > HEADING 2 > HEADING 3: HYPOTHETICAL NOTE CONTENTS. |
Oops, something went wrong.