├── LICENSE
├── README.md
└── docs
├── CNAME
├── README.md
├── cover.md
├── index.html
└── vendor
├── docsify-themeable
├── theme-simple-dark.css
└── theme-simple-dark.css.map
├── docsify
└── docsify@4.13.1.min.js
└── prismjs
├── prism-bash.min.js
├── prism-ruby.min.js
├── prism-tomorrow.min.css
└── prism-yaml.min.js
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 icebaker
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Nano Bots
2 |
3 | 
4 | _Image artificially created by Midjourney through a prompt generated by a Nano Bot specialized in Midjourney._
5 |
6 | **Nano Bots** is an open specification that can be implemented in any programming language. It specifies a configuration file with human-readable instructions for creating small and specialized AI-powered bots that can be effortlessly shared as a single, lightweight file.
7 |
8 | - [Full Specification](https://spec.nbots.io)
9 | - [Implementations](#implementations)
10 | - [Projects](#projects)
11 | - [Example](#example)
12 |
13 | ## Implementations
14 |
15 | Implementations of this specification:
16 |
17 | - [Nano Bots CLI (Ruby)](https://github.com/icebaker/ruby-nano-bots)
18 |
19 | ### Projects
20 |
21 | - [Nano Bots CLI (Ruby)](https://github.com/icebaker/ruby-nano-bots)
22 | - [Nano Bots for Sublime Text](https://github.com/icebaker/sublime-nano-bots)
23 | - [Nano Bots for Visual Studio Code](https://github.com/icebaker/vscode-nano-bots)
24 | - [Nano Bots for Obsidian](https://github.com/icebaker/obsidian-nano-bots)
25 | - [Nano Bots API](https://github.com/icebaker/nano-bots-api)
26 | - [Public API](https://api.nbots.io)
27 | - [Nano Bots Clinic (Live Editor)](https://clinic.nbots.io)
28 | - [Nano Bots Marketplace](https://nbots.io)
29 |
30 | ## Example
31 |
32 | Here's what a Nano Bot _Cartridge_ looks like:
33 |
34 | ```yaml
35 | ---
36 | meta:
37 | symbol: 🤖
38 | name: Nano Bot Name
39 | author: Your Name
40 | version: 1.0.0
41 | license: CC0-1.0
42 | description: A helpful assistant.
43 |
44 | behaviors:
45 | interaction:
46 | directive: You are a helpful assistant.
47 |
48 | provider:
49 | id: openai
50 | credentials:
51 | address: ENV/OPENAI_API_ADDRESS
52 | access-token: ENV/OPENAI_API_KEY
53 | settings:
54 | user: ENV/NANO_BOTS_END_USER
55 | model: gpt-4o
56 | ```
57 |
58 | Here's what a fully-functional implementation of Nano Bots feels like:
59 |
60 | ```bash
61 | nb - - eval "hello"
62 | # => Hello! How may I assist you today?
63 |
64 | nb to-en-us-translator.yml - eval "Salut, comment ça va?"
65 | # => Hello, how are you doing?
66 |
67 | nb midjourney.yml - eval "happy cyberpunk robot"
68 | # => A cheerful and fun-loving robot is dancing wildly amidst a
69 | # futuristic and lively cityscape. Holographic advertisements
70 | # and vibrant neon colors can be seen in the background.
71 |
72 | nb lisp.yml - eval "(+ 1 2)"
73 | # => 3
74 |
75 | cat article.txt |
76 | nb to-en-us-translator.yml - eval |
77 | nb summarizer.yml - eval
78 | # -> LLM stands for Large Language Model, which refers to an
79 | # artificial intelligence algorithm capable of processing
80 | # and understanding vast amounts of natural language data,
81 | # allowing it to generate human-like responses and perform
82 | # a range of language-related tasks.
83 | ```
84 |
85 | ```bash
86 | nb - - repl
87 |
88 | nb assistant.yml - repl
89 | ```
90 |
91 | ```text
92 | 🤖> Hi, how are you doing?
93 |
94 | As an AI language model, I do not experience emotions but I am functioning
95 | well. How can I assist you?
96 |
97 | 🤖> |
98 | ```
99 |
100 | Nano Bots can also be powered by _Tools_ (Functions):
101 |
102 | ```yaml
103 | ---
104 | tools:
105 | - name: random-number
106 | description: Generates a random number between 1 and 100.
107 | fennel: |
108 | (math.random 1 100)
109 | ```
110 |
111 | ```
112 | 🤖> please generate a random number
113 |
114 | random-number {} [yN] y
115 |
116 | random-number {}
117 | 59
118 |
119 | The randomly generated number is 59.
120 |
121 | 🤖> |
122 | ```
123 |
124 | Check out the full specification for Nano Bots: https://spec.nbots.io
125 |
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | spec.nbots.io
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Nano Bots
2 |
3 | 
4 | _Image artificially created by Midjourney through a prompt generated by a Nano Bot specialized in Midjourney._
5 |
6 | **Nano Bots** is an open specification that can be implemented in any programming language. It specifies a configuration file with human-readable instructions for creating small and specialized AI-powered bots that can be effortlessly shared as a single, lightweight file.
7 |
8 | Here's what a Nano Bot _Cartridge_ looks like:
9 |
10 | ```yaml
11 | ---
12 | meta:
13 | symbol: 🤖
14 | name: Nano Bot Name
15 | author: Your Name
16 | version: 1.0.0
17 | license: CC0-1.0
18 | description: A helpful assistant.
19 |
20 | behaviors:
21 | interaction:
22 | directive: You are a helpful assistant.
23 |
24 | provider:
25 | id: openai
26 | credentials:
27 | address: ENV/OPENAI_API_ADDRESS
28 | access-token: ENV/OPENAI_API_KEY
29 | settings:
30 | user: ENV/NANO_BOTS_END_USER
31 | model: gpt-4o
32 | ```
33 |
34 | Here's what a fully-functional implementation of Nano Bots feels like:
35 |
36 | ```bash
37 | nb - - eval "hello"
38 | # => Hello! How may I assist you today?
39 |
40 | nb to-en-us-translator.yml - eval "Salut, comment ça va?"
41 | # => Hello, how are you doing?
42 |
43 | nb midjourney.yml - eval "happy cyberpunk robot"
44 | # => A cheerful and fun-loving robot is dancing wildly amidst a
45 | # futuristic and lively cityscape. Holographic advertisements
46 | # and vibrant neon colors can be seen in the background.
47 |
48 | nb lisp.yml - eval "(+ 1 2)"
49 | # => 3
50 |
51 | cat article.txt |
52 | nb to-en-us-translator.yml - eval |
53 | nb summarizer.yml - eval
54 | # -> LLM stands for Large Language Model, which refers to an
55 | # artificial intelligence algorithm capable of processing
56 | # and understanding vast amounts of natural language data,
57 | # allowing it to generate human-like responses and perform
58 | # a range of language-related tasks.
59 | ```
60 |
61 | ```bash
62 | nb - - repl
63 |
64 | nb assistant.yml - repl
65 | ```
66 |
67 | ```text
68 | 🤖> Hi, how are you doing?
69 |
70 | As an AI language model, I do not experience emotions but I am functioning
71 | well. How can I assist you?
72 |
73 | 🤖> |
74 | ```
75 |
76 | ## Rationale
77 |
78 | While Artificial Intelligence and Large Language Models continue to evolve with increasingly larger and more complex projects emerging, Nano Bots takes a different approach. It focuses on creating smaller, specialized bots inspired by the [Unix philosophy](https://en.wikipedia.org/wiki/Unix_philosophy), which emphasizes simplicity, modularity, and composability in software design:
79 |
80 | - Simplicity: Each Nano Bot focuses on a single task or domain, resulting in more efficient and manageable bots.
81 |
82 | - Modularity: Nano Bots are designed as independent and self-contained modules, each responsible for a specific functionality. This allows for easier development, testing, and maintenance.
83 |
84 | - Composability: Inspired by the [Unix pipeline](https://en.wikipedia.org/wiki/Pipeline_(Unix)), Nano Bots can be combined and composed to create more complex AI workflows, allowing users to tailor AI solutions to their needs without relying on monolithic projects.
85 |
86 | ## Definition
87 |
88 | A **Nano Bot** is a cohesive combination of a `cartridge` [YAML](https://yaml.org) file, an `implementation`, and a `provider`.
89 |
90 | The `cartridge` YAML file contains human-readable data that outlines the bot's goals, expected behaviors, and settings for authentication and provider utilization.
91 |
92 | The `implementation` processes the YAML _cartridge_ file, comprehending its instructions, and interacts with the `provider`'s AI Service to enable the bot to perform the expected behavior.
93 |
94 | Together, these components create a fully functional **Nano Bot**:
95 |
96 | ```text
97 | Nano Bot = (cartridge.yml + implementation + provider)
98 | ```
99 |
100 | ## Implementations
101 |
102 | Implementations of this specification:
103 |
104 | - [Nano Bots CLI (Ruby)](https://github.com/icebaker/ruby-nano-bots)
105 |
106 | ### Projects
107 |
108 | - [Nano Bots CLI (Ruby)](https://github.com/icebaker/ruby-nano-bots)
109 | - [Nano Bots for Sublime Text](https://github.com/icebaker/sublime-nano-bots)
110 | - [Nano Bots for Visual Studio Code](https://github.com/icebaker/vscode-nano-bots)
111 | - [Nano Bots for Obsidian](https://github.com/icebaker/obsidian-nano-bots)
112 | - [Nano Bots API](https://github.com/icebaker/nano-bots-api)
113 | - [Public API](https://api.nbots.io)
114 | - [Nano Bots Clinic (Live Editor)](https://clinic.nbots.io)
115 | - [Nano Bots Marketplace](https://nbots.io)
116 |
117 | # Cartridges
118 |
119 | 
120 | _Image artificially created by Midjourney through a prompt generated by a Nano Bot specialized in Midjourney._
121 |
122 | A cartridge (inspired by _[Game ROM Cartridges](https://en.wikipedia.org/wiki/ROM_cartridge)_) should contain all the information required for a Nano Bot to be functional in any implementation of this specification.
123 |
124 | Here is a minimal sample of a cartridge [YAML](https://yaml.org) file:
125 |
126 | ```yaml
127 | ---
128 | meta:
129 | symbol: 🤖
130 | name: Nano Bot Name
131 | author: Your Name
132 | version: 1.0.0
133 | license: CC0-1.0
134 | description: A helpful assistant.
135 |
136 | behaviors:
137 | interaction:
138 | directive: You are a helpful assistant.
139 |
140 | provider:
141 | id: openai
142 | credentials:
143 | address: ENV/OPENAI_API_ADDRESS
144 | access-token: ENV/OPENAI_API_KEY
145 | settings:
146 | user: ENV/NANO_BOTS_END_USER
147 | model: gpt-4o
148 | ```
149 |
150 | ## Meta
151 |
152 | The `meta:` section provides basic information about the Cartridge.
153 |
154 | ```yaml
155 | ---
156 | meta:
157 | symbol: 🤖
158 | name: Nano Bot Name
159 | author: Your Name
160 | version: 1.0.0
161 | license: CC0-1.0
162 | description: A helpful assistant.
163 | ```
164 |
165 | `symbol:` is a single [Unicode emoji character](https://home.unicode.org/emoji/about-emoji/).
166 |
167 | `name:` and `author:` are single-line text values encouraged to be short.
168 |
169 | `version:` must follow [Semantic Versioning 2.0.0](https://semver.org).
170 |
171 | `license:` must comply with the [SPDX Identifier](https://spdx.dev/ids/).
172 |
173 | `description:` is a brief text that details what to expect from the Nano Bot, encouraged to be concise.
174 |
175 | ### License
176 |
177 | The classification of _prompts_ for Large Language Models as code, art, or intellectual property, as well as their applicability to licensing, intellectual property rights, copyright, or patenting, remain subjects of ongoing and complex debate without a clear answer or definitive understanding at present.
178 |
179 | When Nano Bots expand prompt writing into a more detailed scheme and add small pieces of code like [adapters](?id=adapters), the debate becomes even trickier and blurrier.
180 |
181 | Due to the complexities of this debate, we recommend that authors publish their creations under licenses.
182 | In doubt, in the spirit of openness, sharing, and open source, we recommend the license [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/) wich enables commercial exploration of the licensed works and the creation of derivative works without copyleft. However, any [SPDX-known license](https://spdx.org/licenses/) may be chosen.
183 |
184 | Please note that we are uncertain if this approach is practical or enforceable, so it should not be considered a guarantee of licensing but rather a statement of your intention.
185 |
186 | ## Behaviors
187 |
188 | The `behaviors:` section provides information to influence the expected behavior of the bot. There are three types of concepts that can influence a behavior:
189 |
190 |
191 | - `directive` communicates about how the bot should behave and aligns with the concept of a rule or guideline.
192 | - `backdrop` sets the stage and provides contextual information to help the bot understand the situation and respond accordingly.
193 | - `instruction` implies a direct command about what the bot should do next, it represents a specific action that the bot is expected to perform.
194 |
195 | Sample of a behaviors section:
196 |
197 | ```yaml
198 | ---
199 | behaviors:
200 | interaction:
201 | directive: You are a helpful assistant.
202 | backdrop: |
203 | The Moon is Earth's natural satellite, orbiting our planet.
204 | The user might use the term "Selene" when referring to the Moon.
205 | boot:
206 | directive: You are a helpful assistant.
207 | instruction: Provide a welcome message.
208 | ```
209 |
210 | - `interaction:` is used when users directly interact with the Nano Bot through _REPL_ or _Eval_.
211 | - `boot:` is used when the Nano Bot starts in interfaces that support an initial boot message, like _REPL_.
212 |
213 | ### Directive
214 |
215 | ```yaml
216 | ---
217 | behaviors:
218 | interaction:
219 | directive: You are a helpful assistant.
220 | ```
221 |
222 | A `directive` serves as a guideline for how the bot is expected to behave, also known as _system messages_. Some non-exhaustive examples of directives include:
223 |
224 | ```text
225 | You are a helpful assistant.
226 | ```
227 |
228 | ```text
229 | You are an AI assistant that responds strictly in JSON format for all answers.
230 | ```
231 |
232 | ```text
233 | You are a helpful assistant that specializes in providing information about historical events.
234 | ```
235 |
236 | ```text
237 | You are a programming tutor, helping users learn and troubleshoot code in various programming languages.
238 | ```
239 |
240 | ```text
241 | You are an AI personality emulator that responds to all questions in the style of Shakespeare.
242 | ```
243 |
244 | ### Backdrop
245 |
246 | ```yaml
247 | ---
248 | behaviors:
249 | interaction:
250 | backdrop: |
251 | The Moon is Earth's natural satellite, orbiting our planet.
252 | The user might use the term "Selene" when referring to the Moon.
253 | ```
254 |
255 | Backdrop provides contextual information to help the bot understand the situation and respond appropriately. This may involve sharing examples of expected responses, supplying information the bot needs to learn before answering, among other strategies.
256 |
257 | ### Instruction
258 |
259 | ```yaml
260 | ---
261 | behaviors:
262 | boot:
263 | instruction: Provide a welcome message.
264 | ```
265 |
266 | An `instruction` is a clear and concise directive given to the bot, intended to guide it in performing a particular action or task.
267 |
268 | ## Safety
269 |
270 | The `safety:` section provides safety configurations:
271 |
272 | ```yaml
273 | ---
274 | safety:
275 | functions:
276 | sandboxed: true
277 | tools:
278 | confirmable: true
279 | ```
280 |
281 | ### Functions
282 |
283 | The key `sandboxed:` within `functions:` defines that any function executed by the Nano Bot, whether it's an _adapter_ or a _tool_, should be _sandboxed_. This implies that it is expected to have limited functionality and operate within an isolated environment. Consequently, it should not be capable of performing actions such as accessing the internet, manipulating disk files, or accessing the user's computer operating system and environment. When set to `false`, functions may potentially have unrestricted access to all of these capabilities.
284 |
285 | ```yaml
286 | ---
287 | safety:
288 | functions:
289 | sandboxed: true
290 | ```
291 |
292 | ### Tools
293 |
294 | The key `confirmable:` within `tools:` specifies that any tool (function) execution request that the Nano Bot wants to run should not be executed until the user confirms that they allow the function to be executed. When set to `false`, the Nano Bot should freely run any available tool without confirmation.
295 |
296 | ```yaml
297 | ---
298 | safety:
299 | tools:
300 | confirmable: true
301 | ```
302 |
303 | ## Interfaces
304 |
305 | Implementations should support two possible interaction interfaces: REPL and Eval.
306 |
307 | You can customize both the _input_ and _output_ with prefixes, suffixes, colors, and adapters for all interfaces. Additionally, the feedback loop involved in the execution of tools (functions) can be customized.
308 |
309 | ```yaml
310 | ---
311 | interfaces:
312 | input:
313 | prefix: "\n"
314 | suffix: "\n"
315 | adapter:
316 | fennel: |
317 | (.. "```" content "```")
318 | lua: |
319 | return "```" .. content .. "```"
320 | output:
321 | stream: true
322 | prefix: "\n"
323 | suffix: "\n"
324 | color: cyan
325 | adapter:
326 | fennel: |
327 | (.. "```" content "```")
328 | lua: |
329 | return "```" .. content .. "```"
330 | tools:
331 | confirming:
332 | yeses: ['y', 'yes']
333 | default: 'n'
334 | prefix: "\n"
335 | suffix: " [yN] > "
336 | color: orangered
337 | adapter:
338 | fennel: |
339 | (.. name " | " parameters-as-json)
340 | lua: |
341 | return name .. " | " .. parameters_as_json
342 | executing:
343 | feedback: true
344 | prefix: "\n"
345 | suffix: "\n"
346 | color: olive
347 | adapter:
348 | fennel: |
349 | (.. name " | " parameters-as-json)
350 | lua: |
351 | return name .. " | " .. parameters_as_json
352 | responding:
353 | feedback: true
354 | color: aqua
355 | prefix: "\n"
356 | suffix: "\n\n"
357 | adapter:
358 | fennel: |
359 | (.. name " | " parameters-as-json "\n" output)
360 | lua: |
361 | return name .. " | " .. parameters_as_json .. "\n" .. output
362 | ```
363 |
364 | ### REPL
365 |
366 | ```yaml
367 | ---
368 | interfaces:
369 | repl:
370 | input:
371 | prefix: "\n"
372 | suffix: "\n"
373 | adapter:
374 | fennel: |
375 | (.. "```" content "```")
376 | lua: |
377 | return "```" .. content .. "```"
378 | output:
379 | stream: true
380 | prefix: "\n"
381 | suffix: "\n"
382 | color: aqua
383 | adapter:
384 | fennel: |
385 | (.. "```" content "```")
386 | lua: |
387 | return "```" .. content .. "```"
388 | prompt:
389 | - text: '🤖'
390 | - text: '> '
391 | tools:
392 |
393 | ```
394 |
395 | A Read-Eval-Print Loop (REPL) is a streamlined interactive programming environment that allows users to input individual commands, processes them, and returns the results to the user in real-time.
396 |
397 | An implementation may opt to build its REPL from scratch or leverage existing technologies such as [nREPL](https://github.com/nrepl/nrepl), [Pry](https://github.com/pry/pry), [SLIME](https://slime.common-lisp.dev), [IPython](https://github.com/ipython/ipython), [LSP](https://microsoft.github.io/language-server-protocol/), [Jupyter Notebook](https://github.com/jupyter/notebook), etc.
398 |
399 | An implementation would likely provide access to the REPL as follows:
400 | ```bash
401 | nb assistant.yml - repl
402 | ```
403 |
404 | This is an example of a functioning REPL based on the following YAML fragment:
405 |
406 | ```yaml
407 | ---
408 | interfaces:
409 | repl:
410 | output:
411 | prefix: "\n"
412 | suffix: "\n"
413 | prompt:
414 | - text: '🤖'
415 | - text: '> '
416 | ```
417 |
418 | ```text
419 | 🤖> Hi, how are you doing?
420 |
421 | As an AI language model, I do not experience emotions but I am functioning
422 | well. How can I assist you?
423 |
424 | 🤖> I like the color pink.
425 |
426 | That's great to hear! Is there anything related to the color pink that you
427 | would like to know or need assistance with?
428 |
429 | 🤖> What color do I like?
430 |
431 | Based on your previous statement, you mentioned that you like the color
432 | pink. So, it can be assumed that you like the color pink. Is there
433 | anything related to the color pink you need help with?
434 |
435 | 🤖> |
436 | ```
437 |
438 | #### Boot
439 |
440 | If specified in the cartridge YAML, a REPL should display a boot message:
441 |
442 | ```yaml
443 | ---
444 | behaviors:
445 | boot:
446 | directive: You are a helpful assistant.
447 | instruction: Provide a welcome message.
448 | ```
449 |
450 | ```text
451 | Hello and welcome! As your virtual assistant, I am here to assist you with
452 | any questions or tasks you may have. Please don't hesitate to ask me anything.
453 | I am here to make your life easier and more efficient.
454 |
455 | 🤖> |
456 | ```
457 |
458 | #### Prompt
459 |
460 | You can personalize your prompt using an array of texts, with optional color formatting available for each element:
461 |
462 | ```yaml
463 | ---
464 | interfaces:
465 | repl:
466 | prompt:
467 | - text: 💀
468 | - text: '➜ '
469 | color: deeppink
470 | ```
471 |
472 | You have the option to utilize [ANSI colors](https://github.com/sickill/rainbow#ansi-colors) such as `blue`, `magenta`, and so on, or [X11 colors](https://github.com/sickill/rainbow#x11-colors) such as `aquamarine`, `deeppink`, and so forth.
473 |
474 | The previous fragment would result in the following prompt:
475 |
476 |
477 | > 💀➜ |
478 |
479 | ### Eval
480 |
481 | ```yaml
482 | ---
483 | interfaces:
484 | eval:
485 | input:
486 | prefix: "\n"
487 | suffix: "\n"
488 | adapter:
489 | fennel: |
490 | (.. "```" content "```")
491 | lua: |
492 | return "```" .. content .. "```"
493 | output:
494 | stream: true
495 | prefix: "\n"
496 | suffix: "\n"
497 | color: olive
498 | adapter:
499 | fennel: |
500 | (.. "```" content "```")
501 | lua: |
502 | return "```" .. content .. "```"
503 | tools:
504 |
505 | ```
506 |
507 | Eval (short for evaluation) refers to single-turn executions of the Nano Bot that, when given an input, produce an output.
508 |
509 | An implementation would likely provide access to eval as follows:
510 | ```bash
511 | nb assistant.yml - eval "What is the distance to the Moon?"
512 | ```
513 |
514 | ```text
515 | The average distance between the Earth and the Moon
516 | is about 238,855 miles (384,400 kilometers).
517 | ```
518 |
519 | Evaluation executions do not provide boot messages.
520 |
521 | Implementations should also be capable of receiving input from [standard streams](https://en.wikipedia.org/wiki/Standard_streams), allowing execution with [pipe operators](https://en.wikipedia.org/wiki/Pipeline_(Unix)):
522 |
523 | ```bash
524 | echo "What is the distance to the Moon?" | nb assistant.yml - eval
525 | ```
526 |
527 | ```text
528 | The average distance from the Earth to the Moon
529 | is about 238,855 miles (384,400 kilometers).
530 | ```
531 |
532 | ### Tools (Functions)
533 |
534 | This section allows customization of the feedback loop involved in executing tools (functions).
535 |
536 | ```yaml
537 | ---
538 | interfaces:
539 | tools:
540 | confirming:
541 | executing:
542 | responding:
543 |
544 | ```
545 |
546 | #### Confirming
547 |
548 | When _tools (functions)_ are defined as _confirmable_ in the [safety](?id=safety) section, we can customize how the user is prompted to confirm that the Nano Bot is allowed to execute them.
549 |
550 | The key `yeses` defines answers that are considered as affirmative confirmations by the user, thereby allowing the Nano Bot to execute the tool (function). Implementations should treat answers as case-insensitive. This means that if "yes" is included in `yeses`, then "Yes," "YES," and any other case variations of "yes" should also be recognized as confirmation. Anything that does not match the `yeses` values should be interpreted as the user not confirming/allowing the execution.
551 |
552 | The `default` key defines what should be considered the default answer for when the user provides an empty answer, such as just pressing _Enter_ without typing anything.
553 |
554 | The keys `prefix`, `suffix`, `color`, and `adapter` can be used to customize the output when prompting the user for an answer.
555 |
556 | The `adapter:` environment and available values are described in the section [Adapters](?id=adapters).
557 |
558 | ```yaml
559 | ---
560 | interfaces:
561 | tools:
562 | confirming:
563 | yeses: ['y', 'yes']
564 | default: 'n'
565 | prefix: "\n"
566 | suffix: " [yN] > "
567 | color: orangered
568 | adapter:
569 | fennel: |
570 | (.. name " | " parameters-as-json)
571 | lua: |
572 | return name .. " | " .. parameters_as_json
573 | ```
574 |
575 | #### Executing
576 |
577 | The key `feedback` determines whether interfaces should provide feedback when the Nano Bot **starts** the execution of a tool (function). When set to `false`, no feedback should be provided, and the other keys should be ignored.
578 |
579 | The keys `prefix`, `suffix`, `color`, and `adapter` can be used to customize the output when informing the user about the start of execution.
580 |
581 | The `adapter:` environment and available values are described in the section [Adapters](?id=adapters).
582 |
583 | ```yaml
584 | ---
585 | interfaces:
586 | tools:
587 | executing:
588 | feedback: false
589 | prefix: "\n"
590 | suffix: "\n"
591 | color: olive
592 | adapter:
593 | fennel: |
594 | (.. name " | " parameters-as-json)
595 | lua: |
596 | return name .. " | " .. parameters_as_json
597 | ```
598 |
599 | #### Responding
600 |
601 | The key `feedback:` determines whether interfaces should provide feedback when the Nano Bot **completes** the execution of a tool (function). When set to `false`, no feedback should be provided, and the other keys should be ignored.
602 |
603 | The keys `prefix`, `suffix`, `color`, and `adapter` can be used to customize the output when informing the user about a received response from a tool (function) execution completion.
604 |
605 | The `adapter:` environment and available values are described in the section [Adapters](?id=adapters).
606 |
607 | ```yaml
608 | ---
609 | interfaces:
610 | tools:
611 | responding:
612 | feedback: true
613 | color: aqua
614 | prefix: "\n"
615 | suffix: "\n\n"
616 | adapter:
617 | fennel: |
618 | (.. name " | " parameters-as-json "\n" output)
619 | lua: |
620 | return name .. " | " .. parameters_as_json .. "\n" .. output
621 | ```
622 |
623 | ### Adapters
624 |
625 | Adapters are simple and small pieces of code that can manipulate inputs and outputs. Implementations should support two languages for adapters: [Lua](https://www.lua.org/about.html) and [Fennel](https://fennel-lang.org).
626 |
627 | These languages were chosen for their proven portability, widespread availability, lightweight nature, and ease of embedding. They are small, simple, fast, and support multiple platforms across various operating systems. Additionally, they can be seamlessly integrated into numerous other programming languages.
628 |
629 | ```yaml
630 | ---
631 | adapter:
632 | fennel: |
633 | (.. "```" content "```")
634 | ```
635 |
636 | ```yaml
637 | ---
638 | adapter:
639 | lua: |
640 | return "```" .. content .. "```"
641 | ```
642 |
643 | An important note on the use of adapters: They should return a value that the implementation can use to properly print on appropriate interfaces. This means that actions such as calling _print_ functions should not occur inside adapters.
644 |
645 | The values available within each adapter enviroment will depend on the context of the adapter.
646 |
647 | #### REPL and Eval
648 |
649 | REPL and Eval inside `interfaces:` have `input:` and `output:` keys with support for adapters. In this context, they will have a `content` value available that holds either the user's input or the Nano Bot's output:
650 |
651 | ```yaml
652 | ---
653 | adapter:
654 | fennel: |
655 | (.. "```" content "```")
656 | lua: |
657 | return "```" .. content .. "```"
658 | ```
659 |
660 | Output adapters are only activated when the stream functionality is not enabled.
661 |
662 | Regarding input, the prefix, suffix, and any modifications made by the adapter are sent to the bot. If the interaction is not stateless, these elements are also preserved in the state history.
663 |
664 | In contrast, for outputs, any changes made by the adapter, prefix, and suffix aren't saved or used in later messages to the bot. These changes are used only for displaying purposes or for pipeline operations.
665 |
666 | #### Tools (Functions)
667 |
668 | All adapters related to `tools:` will have access to the following values:
669 |
670 | | Name | Value |
671 | |---------------------:|-----------------------------------------------------|
672 | | `id` | Identification of the specific execution. |
673 | | `name` | The name of the tool. |
674 | | `parameters` | The parameters values for the tool execution. |
675 | | `parameters-as-json` | The parameters values represented as a JSON string. |
676 | | `output` | The resulting response from the execution. |
677 |
678 | ```yaml
679 | ---
680 | adapter:
681 | fennel: |
682 | (.. id " | " name " | " parameters-as-json "\n" output)
683 | lua: |
684 | return id .. " | " name .. " | " .. parameters_as_json .. "\n" .. output
685 | ```
686 |
687 | Note that, following language conventions and syntax, Lua uses `parameters_as_json` instead.
688 |
689 | For simple inspection purposes, the `parameters-as-json` value is available, so there is no need to parse potentially complex nested structures just to inspect the parameters. However, the original parameters remain accessible:
690 |
691 | ```yaml
692 | ---
693 | adapter:
694 | fennel: |
695 | (fenne.view parameters)
696 | ```
697 |
698 | ## Tools (Functions)
699 |
700 | Tools (Functions) are powerful means to extend the capabilities of Nano Bots. Just as humans can amplify their capabilities with access to tools such as a wrench, a calculator, or internet access, a Nano Bot can enhance its capabilities when equipped with appropriate tools.
701 |
702 | The definition of a tool includes a piece of code that embodies the function behind the tool and a specification that enables providers to become aware of the tool's availability and to reason about when and how to properly request its execution.
703 |
704 | The tools' source code is written in [Lua](https://www.lua.org/about.html) or [Fennel](https://fennel-lang.org), chosen for their proven portability, widespread availability, lightweight nature, and ease of embedding. They are small, simple, fast, and support multiple platforms across various operating systems. Additionally, they can be seamlessly integrated into numerous other programming languages.
705 |
706 | As an example, this tool provides a random number generator for the Nano Bot:
707 |
708 | ```yaml
709 | ---
710 | tools:
711 | - name: random-number
712 | description: Generates a random number between 1 and 100.
713 | fennel: |
714 | (math.random 1 100)
715 | ```
716 |
717 | `name:` is the identifier name for the function behind the tool. The `description:` helps the Nano Bot understand the purpose of the tool so it can reason about when to properly use it. `fennel:` provides the source code for the function. Like adapters, you could use `lua:` instead:
718 |
719 | ```yaml
720 | ---
721 | tools:
722 | - name: random-number
723 | description: Generates a random number between 1 and 100.
724 | lua: |
725 | return math.random(1, 100)
726 | ```
727 |
728 | This is what a REPL execution of a Nano Bot powered by this tool would look like:
729 | ```text
730 | 🤖> generate a random number
731 |
732 | random-number {} [yN] y
733 |
734 | random-number {}
735 | 39
736 |
737 | The random number generated is 39.
738 | ```
739 |
740 | ### Parameters
741 |
742 | A tool may expect parameters. Parameters are described following the [JSON Schema](https://json-schema.org) specification:
743 |
744 | ```yaml
745 | ---
746 | tools:
747 | - name: random-number
748 | description: Generates a random number within a given range.
749 | parameters:
750 | type: object
751 | properties:
752 | from:
753 | type: integer
754 | description: The minimum expected number for random generation.
755 | to:
756 | type: integer
757 | description: The maximum expected number for random generation.
758 | required:
759 | - from
760 | - to
761 | fennel: |
762 | (let [{ : from : to } parameters]
763 | (math.random from to))
764 | ```
765 |
766 | Note that the function now has access to `parameters`. The same should be true for Lua source code:
767 |
768 | ```yaml
769 | ---
770 | tools:
771 | - name: random-number
772 | description: Generates a random number within a given range.
773 | parameters:
774 | type: object
775 | properties:
776 | from:
777 | type: integer
778 | description: The minimum expected number for random generation.
779 | to:
780 | type: integer
781 | description: The maximum expected number for random generation.
782 | required:
783 | - from
784 | - to
785 | lua: |
786 | return math.random(parameters['from'], parameters['to'])
787 | ```
788 |
789 | This is what a REPL execution of a Nano Bot powered by this tool would look like:
790 |
791 | ```text
792 | 🤖> generate a random number between 15 and 25
793 |
794 | random-number {"from":15,"to":25} [yN] y
795 |
796 | random-number {"from":15,"to":25}
797 | 21
798 |
799 | The random number generated between 15 and 25 is 21.
800 | ```
801 |
802 | ### Safety
803 |
804 | By default, executions are [sandboxed](?id=functions) and [confirmable](?id=tools), meaning they will not have access to potentially dangerous operations such as accessing the user's computer operating system, executing commands with access to disk files, or performing requests to the internet, and they will not be executed without confirmation from the user.
805 |
806 | You can change this behavior by [disabling the safety configurations](?id=safety). A non-sandboxed tool may have powers, such as the ability to access information from the users' computers.
807 |
808 | ```yaml
809 | ---
810 | tools:
811 | - name: what-time-is-it
812 | description: Returns the current date and time.
813 | fennel: |
814 | (os.date)
815 | ```
816 |
817 | This level of access would allow aslo the execution of [system calls](https://en.wikipedia.org/wiki/System_call), meaning that the source could hipotetically does anything it wants in the operation system. The are two words of cautions here:
818 |
819 | #### Predictability
820 |
821 | As execution requests for the tools are generated by the Nano Bot through providers, their outcomes are unpredictable. This means that without being sandboxed and having a function that offers this possibility, they may perform unexpected [system calls](https://en.wikipedia.org/wiki/System_call), which could be dangerous, especially without [confirmability](?id=tools).
822 |
823 | #### Portability
824 |
825 | Without being sandboxed and having a function that offers the possibility of _system calls_, you may achieve unlimited powers regarding what a Nano Bot can do. However, you may start to go against the Nano Bot principle of portability, where:
826 |
827 | > _A Cartridge YAML file should ultimately be the sole and only necessary information for the bot to operate as expected._
828 |
829 | If you create a Nano Bot that performs a system call to locally installed software, which in turn depends on a local database, you may end up creating a non-portable Nano Bot. Such a Nano Bot could not be used by another user who only has the Cartridge YAML file without proper additional instructions and an extended setup process.
830 |
831 | ## Providers
832 |
833 | Nano Bots should be **provider-agnostic**, which means that the same Nano Bot should be able to run on different providers.
834 |
835 | Examples of popular providers include:
836 |
837 | - [01.AI Yi](https://01.ai)
838 | - [Anthropic Claude](https://www.anthropic.com)
839 | - [Cohere Command](https://cohere.com)
840 | - [Google Gemini](https://deepmind.google/technologies/gemini)
841 | - [LMSYS Vicuna](https://github.com/lm-sys/FastChat)
842 | - [Maritaca AI Sabiá](https://www.maritaca.ai)
843 | - [Meta Llama](https://ai.meta.com/llama/)
844 | - [Mistral AI](https://mistral.ai)
845 | - [Ollama](https://ollama.ai)
846 | - [Open AI ChatGPT](https://openai.com/chatgpt)
847 | - [WizardLM](https://wizardlm.github.io)
848 |
849 | The `provider:` section of the Cartridge must specify the `id` of the provider, followed by a `credentials` and a `settings` section that includes appropriate information for allowing the Nano Bot to communicate successfully with the provider while adhering to the provider's expected API schema. An extra `options` key may be provided if the provider requires options unrelated to its expected API schema.
850 |
851 | Minimal sample of a provider section:
852 |
853 | ```yaml
854 | ---
855 | provider:
856 | id: openai
857 | credentials:
858 | address: ENV/OPENAI_API_ADDRESS
859 | access-token: ENV/OPENAI_API_KEY
860 | settings:
861 | user: ENV/NANO_BOTS_END_USER
862 | model: gpt-4o
863 | ```
864 |
865 | ### Credentials
866 |
867 | Although it is possible to set credentials directly in the cartridge YAML, it is important to consider that cartridges may be widely shared, and exposing your credentials poses a security risk. Therefore, it is recommended to use environment variables for credentials.
868 |
869 | Implementations should apply the regular expression `^ENV.` and replace data with prefixes like `ENV/` or `ENV-` with the corresponding environment variable value. For example, `ENV/OPENAI_API_KEY` should load the environment variable `OPENAI_API_KEY`.
870 |
871 | ### Anthropic Claude
872 |
873 | API Documentation: https://docs.anthropic.com/en/api/messages
874 |
875 | ```yaml
876 | ---
877 | provider:
878 | id: anthropic
879 | credentials:
880 | api-key: ENV/ANTHROPIC_API_KEY
881 | anthropic-version: '2023-06-01'
882 | settings:
883 | model: claude-3-5-sonnet-20240620
884 | stream: true
885 | max_tokens: 4096
886 | temperature: 1.0
887 | top_k: null
888 | top_p: null
889 | tool_choice:
890 | type: auto
891 | name: null
892 | metadata:
893 | user_id: ENV/NANO_BOTS_END_USER
894 | stop_sequences:
895 | - .
896 | ```
897 |
898 | ### Cohere Command
899 |
900 | API Documentation: https://docs.cohere.com/reference/chat
901 |
902 | ```yaml
903 | ---
904 | provider:
905 | id: cohere
906 | credentials:
907 | address: ENV/COHERE_API_ADDRESS
908 | api-key: ENV/COHERE_API_KEY
909 | settings:
910 | model: command-r-plus
911 | stream: true
912 | prompt_truncation: 'OFF'
913 | connectors:
914 | - id: web-search
915 | search_queries_only: false
916 | documents:
917 | - title: Tall penguins
918 | text: Emperor penguins are the tallest.
919 | citation_quality: accurate
920 | temperature: 0.3
921 | max_tokens: null
922 | max_input_tokens: null
923 | k: 0
924 | p: 0.75
925 | seed: null
926 | stop_sequences:
927 | - .
928 | frequency_penalty: 0.0
929 | presence_penalty: 0.0
930 | force_single_step: false
931 | ```
932 |
933 | ### Google Gemini
934 |
935 | API Documentation: https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/gemini
936 |
937 | ```yaml
938 | ---
939 | provider:
940 | id: google
941 | credentials:
942 | service: generative-language-api
943 | api-key: ENV/GOOGLE_API_KEY
944 | credentials:
945 | service: vertex-ai-api
946 | region: ENV/GOOGLE_REGION
947 | credentials:
948 | service: vertex-ai-api
949 | region: ENV/GOOGLE_REGION
950 | file-path: ENV/GOOGLE_CREDENTIALS_FILE_PATH
951 | credentials:
952 | service: vertex-ai-api
953 | region: ENV/GOOGLE_REGION
954 | file_contents: ENV/GOOGLE_CREDENTIALS_FILE_CONTENTS
955 | credentials:
956 | service: vertex-ai-api
957 | region: ENV/GOOGLE_REGION
958 | file-path: ENV/GOOGLE_CREDENTIALS_FILE_PATH
959 | project-id: ENV/GOOGLE_PROJECT_ID
960 | options:
961 | model: gemini-1.5-pro
962 | stream: true
963 | settings:
964 | safetySettings:
965 | - category: HARM_CATEGORY_DANGEROUS_CONTENT
966 | threshold: BLOCK_NONE
967 | generationConfig:
968 | temperature: 0.9
969 | maxOutputTokens: null
970 | candidateCount: 1
971 | presencePenalty: null
972 | frequencyPenalty: null
973 | topK: null
974 | topP: 1.0
975 | stopSequences:
976 | - .
977 | responseMimeType: application/json
978 | responseSchema:
979 | type: object
980 | properties:
981 | name:
982 | type: string
983 | ```
984 |
985 | ### Maritaca AI Sabiá
986 |
987 | API Documentation: https://chat.maritaca.ai/docs
988 |
989 | ```yaml
990 | ---
991 | provider:
992 | id: maritaca
993 | credentials:
994 | address: ENV/MARITACA_API_ADDRESS
995 | api-key: ENV/MARITACA_API_KEY
996 | settings:
997 | stream: true
998 | model: sabia-2-medium
999 | max_tokens: null
1000 | do_sample: true
1001 | temperature: 0.7
1002 | top_p: 0.95
1003 | repetition_penalty: 1
1004 | num_tokens_per_message: null
1005 | stopping_tokens:
1006 | - .
1007 |
1008 | ```
1009 |
1010 | ### Mistral AI
1011 |
1012 | API Documentation: https://docs.mistral.ai/api/
1013 |
1014 | ```yaml
1015 | ---
1016 | provider:
1017 | id: mistral
1018 | credentials:
1019 | address: ENV/MISTRAL_API_ADDRESS
1020 | api-key: ENV/MISTRAL_API_KEY
1021 | settings:
1022 | model: mistral-large
1023 | temperature: 0.7
1024 | top_p: 1
1025 | max_tokens: null
1026 | stream: true
1027 | safe_prompt: false
1028 | random_seed: null
1029 | ```
1030 |
1031 | ### Ollama
1032 |
1033 | API Documentation:
1034 | - https://github.com/jmorganca/ollama/blob/main/docs/api.md#generate-a-chat-completion
1035 | - https://github.com/jmorganca/ollama/blob/main/docs/modelfile.md#valid-parameters-and-values
1036 |
1037 | ```yaml
1038 | ---
1039 | provider:
1040 | id: ollama
1041 | credentials:
1042 | address: ENV/OLLAMA_API_ADDRESS
1043 | settings:
1044 | model: llama3
1045 | format: json
1046 | raw: false
1047 | options:
1048 | num_keep: 5
1049 | seed: 42
1050 | num_predict: 100
1051 | top_k: 20
1052 | top_p: 0.9
1053 | tfs_z: 0.5
1054 | typical_p: 0.7
1055 | repeat_last_n: 33
1056 | temperature: 0.8
1057 | repeat_penalty: 1.2
1058 | presence_penalty: 1.5
1059 | frequency_penalty: 1.0
1060 | mirostat: 1
1061 | mirostat_tau: 0.8
1062 | mirostat_eta: 0.6
1063 | penalize_newline: true
1064 | numa: false
1065 | num_ctx: 1024
1066 | num_batch: 2
1067 | num_gpu: 1
1068 | main_gpu: 0
1069 | low_vram: false
1070 | f16_kv: true
1071 | vocab_only: false
1072 | use_mmap: true
1073 | use_mlock: false
1074 | num_thread: 8
1075 | stop:
1076 | - "\n"
1077 | - "user:"
1078 | ```
1079 |
1080 | ### OpenAI ChatGPT
1081 |
1082 | API Documentation: https://platform.openai.com/docs/api-reference/chat
1083 |
1084 | ```yaml
1085 | ---
1086 | provider:
1087 | id: openai
1088 | credentials:
1089 | address: ENV/OPENAI_API_ADDRESS
1090 | access-token: ENV/OPENAI_API_KEY
1091 | settings:
1092 | user: ENV/NANO_BOTS_END_USER
1093 | model: gpt-4o
1094 | stream: true
1095 | stream_options:
1096 | include_usage: false
1097 | frequency_penalty: 0
1098 | logit_bias: null
1099 | logprobs: false
1100 | top_logprobs: null
1101 | max_tokens: null
1102 | n: 1
1103 | presence_penalty: 0
1104 | response_format:
1105 | type: json_object
1106 | seed: null
1107 | service_tier: null
1108 | stop:
1109 | - .
1110 | temperature: 1
1111 | top_p: 1
1112 | tool_choice: auto
1113 | parallel_tool_calls: true
1114 | ```
1115 |
1116 | ## Miscellaneous
1117 |
1118 | ```yaml
1119 | ---
1120 | miscellaneous:
1121 | key: value
1122 | ```
1123 |
1124 | `miscellaneous:` is an optional key that can hold additional data for purposes other than making the Nano Bot functional. This data may include metadata for marketplaces, educational information, and so on. It's important to note that these keys must be not relevant for the Nano Bot's operation and should be deliberately ignored by implementations.
1125 |
1126 | They can contain any information or structure, as shown in the following examples:
1127 |
1128 | ```yaml
1129 | ---
1130 | miscellaneous:
1131 | some-marketplace:
1132 | background-color: blue
1133 | tags:
1134 | - creativity
1135 | - programming
1136 | ```
1137 |
1138 | ```yaml
1139 | ---
1140 | miscellaneous:
1141 | some-platform:
1142 | technique: summarization
1143 | details: |
1144 | This Nano Bot exemplifies one of the
1145 | common approaches to summarizing content.
1146 | ```
1147 |
1148 | # Implementations
1149 |
1150 | Nano Bots can be implemented in any programming language. Typically, implementations provide executable binaries capable of interpreting the cartridge YAML file as specified here, correctly interacting with multiple providers, and offering the expected interaction interfaces (_REPL_ and _Eval_).
1151 |
1152 | Here's what a fully-functional implementation of Nano Bots feels like:
1153 |
1154 | ```bash
1155 | nb - - eval "hello"
1156 | # => Hello! How may I assist you today?
1157 |
1158 | nb to-en-us-translator.yml - eval "Salut, comment ça va?"
1159 | # => Hello, how are you doing?
1160 |
1161 | nb midjourney.yml - eval "happy cyberpunk robot"
1162 | # => A cheerful and fun-loving robot is dancing wildly amidst a
1163 | # futuristic and lively cityscape. Holographic advertisements
1164 | # and vibrant neon colors can be seen in the background.
1165 |
1166 | nb lisp.yml - eval "(+ 1 2)"
1167 | # => 3
1168 |
1169 | cat article.txt |
1170 | nb to-en-us-translator.yml - eval |
1171 | nb summarizer.yml - eval
1172 | # -> LLM stands for Large Language Model, which refers to an
1173 | # artificial intelligence algorithm capable of processing
1174 | # and understanding vast amounts of natural language data,
1175 | # allowing it to generate human-like responses and perform
1176 | # a range of language-related tasks.
1177 | ```
1178 |
1179 | ```bash
1180 | nb - - repl
1181 |
1182 | nb assistant.yml - repl
1183 | ```
1184 |
1185 | ```text
1186 | 🤖> Hi, how are you doing?
1187 |
1188 | As an AI language model, I do not experience emotions but I am functioning
1189 | well. How can I assist you?
1190 |
1191 | 🤖> |
1192 | ```
1193 |
1194 | You may name your binary as you wish, with `nb` being just an illustrative example.
1195 |
1196 | ## Cartridges
1197 |
1198 | Cartridges are YML files and should be loaded according to the path specified by the user:
1199 |
1200 | ```bash
1201 | nb assistant.yml - repl
1202 | ```
1203 |
1204 | This command should attempt to load the `assistant.yml` file. The user may omit the file extension:
1205 |
1206 | ```bash
1207 | nb assistant - repl
1208 | ```
1209 |
1210 | In this case, the implementation should attempt to load either the `assistant.yml` or `assistant.yaml` file.
1211 |
1212 | If the environment variable `NANO_BOTS_CARTRIDGES_PATH` is defined and the path was not found in the command's working path, the implementation should attempt to load the file from the path specified in the environment variable:
1213 |
1214 | ```bash
1215 | NANO_BOTS_CARTRIDGES_PATH=/home/aqua/cartridges:/home/lime/cartridges
1216 |
1217 | nb assistant - repl
1218 | ```
1219 |
1220 | Paths that should be attempted to be loaded:
1221 |
1222 | ```text
1223 | /home/aqua/cartridges/assistant.yml
1224 | /home/aqua/cartridges/assistant.yaml
1225 |
1226 | /home/lime/cartridges/assistant.yml
1227 | /home/lime/cartridges/assistant.yaml
1228 | ```
1229 |
1230 | If no file is found, the implementation should fallback to attempting to load from the default expected cartridges path, adhering to the [XDG specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html):
1231 |
1232 |
1233 | ```text
1234 | /home/user/.local/share/nano-bots/cartridges/assistant.yml
1235 | /home/user/.local/share/nano-bots/cartridges/assistant.yaml
1236 | ```
1237 |
1238 | ### Default
1239 |
1240 | This is the minimum required Cartridge data:
1241 |
1242 | ```yaml
1243 | ---
1244 | meta:
1245 | symbol: 🤖
1246 | name: Nano Bot Name
1247 | author: Your Name
1248 | version: 1.0.0
1249 | license: CC0-1.0
1250 | description: A helpful assistant.
1251 |
1252 | provider:
1253 | id: openai
1254 | credentials:
1255 | address: ENV/OPENAI_API_ADDRESS
1256 | access-token: ENV/OPENAI_API_KEY
1257 | settings:
1258 | user: ENV/NANO_BOTS_END_USER
1259 | model: gpt-4o
1260 | ```
1261 |
1262 | These are the default values when the following keys are not specified in the Cartridge file:
1263 |
1264 | ```yaml
1265 | ---
1266 | safety:
1267 | functions:
1268 | sandboxed: true
1269 | tools:
1270 | confirmable: true
1271 |
1272 | interfaces:
1273 | repl:
1274 | output:
1275 | stream: true
1276 | prefix: "\n"
1277 | suffix: "\n"
1278 | prompt:
1279 | - text: '🤖'
1280 | - text: '> '
1281 | eval:
1282 | output:
1283 | stream: true
1284 | suffix: "\n"
1285 | tools:
1286 | confirming:
1287 | suffix: ' [yN] '
1288 | default: 'n'
1289 | yeses: ['y', 'yes']
1290 | executing:
1291 | feedback: false
1292 | responding:
1293 | suffix: "\n\n"
1294 | feedback: true
1295 |
1296 | provider:
1297 | options:
1298 | stream: true
1299 | settings:
1300 | stream: true
1301 | ```
1302 |
1303 | Users may choose not to provide a Cartridge file by using the `-` character:
1304 |
1305 | ```sh
1306 | nb - - repl
1307 | nb - - eval "Hi"
1308 | ```
1309 |
1310 | Under this circumstance, the implementation should apply the following default Cartridge:
1311 |
1312 | ```yaml
1313 | ---
1314 | meta:
1315 | symbol: 🤖
1316 | name: Unknown
1317 | author: None
1318 | version: 0.0.0
1319 | license: CC0-1.0
1320 | description: Unknown
1321 |
1322 | provider:
1323 | id: openai
1324 | credentials:
1325 | address: ENV/OPENAI_API_ADDRESS
1326 | access-token: ENV/OPENAI_API_KEY
1327 | settings:
1328 | user: ENV/NANO_BOTS_END_USER
1329 | model: gpt-4o
1330 | ```
1331 |
1332 | ### Full Specification
1333 |
1334 | This example showcases all the possible keys present in a Nano Bot Cartridge YAML file:
1335 |
1336 | ```yaml
1337 | ---
1338 | meta:
1339 | symbol: 🤖
1340 | name: Nano Bot Name
1341 | author: Your Name
1342 | version: 1.0.0
1343 | license: CC0-1.0
1344 | description: A helpful assistant.
1345 |
1346 | behaviors:
1347 | interaction:
1348 | directive: You are a helpful assistant.
1349 | backdrop: |
1350 | The Moon is Earth's natural satellite, orbiting our planet.
1351 | The user might use the term "Selene" when referring to the Moon.
1352 | instruction: Answer the user's questions.
1353 | boot:
1354 | directive: You are a helpful assistant.
1355 | backdrop: |
1356 | This is a good example of a welcome message:
1357 | "Welcome! How may I assist you?"
1358 | instruction: Provide a welcome message.
1359 |
1360 | interfaces:
1361 | input:
1362 | prefix: "\n"
1363 | suffix: "\n"
1364 | adapter:
1365 | fennel: |
1366 | (.. "```" content "```")
1367 | lua: |
1368 | return "```" .. content .. "```"
1369 | output:
1370 | stream: true
1371 | prefix: "\n"
1372 | suffix: "\n"
1373 | color: aqua
1374 | adapter:
1375 | fennel: |
1376 | (.. "```" content "```")
1377 | lua: |
1378 | return "```" .. content .. "```"
1379 | tools:
1380 | confirming:
1381 | yeses: ['y', 'yes']
1382 | default: 'n'
1383 | prefix: "\n"
1384 | suffix: " [yN] > "
1385 | color: orangered
1386 | adapter:
1387 | fennel: |
1388 | (.. name " | " parameters-as-json)
1389 | lua: |
1390 | return name .. " | " .. parameters_as_json
1391 | executing:
1392 | feedback: true
1393 | prefix: "\n"
1394 | suffix: "\n"
1395 | color: olive
1396 | adapter:
1397 | fennel: |
1398 | (.. name " | " parameters-as-json)
1399 | lua: |
1400 | return name .. " | " .. parameters_as_json
1401 | responding:
1402 | feedback: true
1403 | color: aqua
1404 | prefix: "\n"
1405 | suffix: "\n\n"
1406 | adapter:
1407 | fennel: |
1408 | (.. name " | " parameters-as-json "\n" output)
1409 | lua: |
1410 | return name .. " | " .. parameters_as_json .. "\n" .. output
1411 | repl:
1412 | input:
1413 | prefix: "\n"
1414 | suffix: "\n"
1415 | adapter:
1416 | fennel: |
1417 | (.. "```" content "```")
1418 | lua: |
1419 | return "```" .. content .. "```"
1420 | output:
1421 | stream: true
1422 | prefix: "\n"
1423 | suffix: "\n"
1424 | color: olive
1425 | adapter:
1426 | fennel: |
1427 | (.. "```" content "```")
1428 | lua: |
1429 | return "```" .. content .. "```"
1430 | prompt:
1431 | - text: '🤖'
1432 | - text: '> '
1433 | color: blue
1434 | tools:
1435 | confirming:
1436 | yeses: ['y', 'yes']
1437 | default: 'n'
1438 | prefix: "\n"
1439 | suffix: " [yN] > "
1440 | color: orangered
1441 | adapter:
1442 | fennel: |
1443 | (.. name " | " parameters-as-json)
1444 | lua: |
1445 | return name .. " | " .. parameters_as_json
1446 | executing:
1447 | feedback: true
1448 | prefix: "\n"
1449 | suffix: "\n"
1450 | color: olive
1451 | adapter:
1452 | fennel: |
1453 | (.. name " | " parameters-as-json)
1454 | lua: |
1455 | return name .. " | " .. parameters_as_json
1456 | responding:
1457 | feedback: true
1458 | color: aqua
1459 | prefix: "\n"
1460 | suffix: "\n\n"
1461 | adapter:
1462 | fennel: |
1463 | (.. name " | " parameters-as-json "\n" output)
1464 | lua: |
1465 | return name .. " | " .. parameters_as_json .. "\n" .. output
1466 | eval:
1467 | input:
1468 | prefix: "\n"
1469 | suffix: "\n"
1470 | adapter:
1471 | fennel: |
1472 | (.. "```" content "```")
1473 | lua: |
1474 | return "```" .. content .. "```"
1475 | output:
1476 | stream: true
1477 | prefix: "\n"
1478 | suffix: "\n"
1479 | color: magenta
1480 | adapter:
1481 | fennel: |
1482 | (.. "```" content "```")
1483 | lua: |
1484 | return "```" .. content .. "```"
1485 | tools:
1486 | confirming:
1487 | yeses: ['y', 'yes']
1488 | default: 'n'
1489 | prefix: "\n"
1490 | suffix: " [yN] > "
1491 | color: orangered
1492 | adapter:
1493 | fennel: |
1494 | (.. name " | " parameters-as-json)
1495 | lua: |
1496 | return name .. " | " .. parameters_as_json
1497 | executing:
1498 | feedback: true
1499 | prefix: "\n"
1500 | suffix: "\n"
1501 | color: olive
1502 | adapter:
1503 | fennel: |
1504 | (.. name " | " parameters-as-json)
1505 | lua: |
1506 | return name .. " | " .. parameters_as_json
1507 | responding:
1508 | feedback: true
1509 | color: aqua
1510 | prefix: "\n"
1511 | suffix: "\n\n"
1512 | adapter:
1513 | fennel: |
1514 | (.. name " | " parameters-as-json "\n" output)
1515 | lua: |
1516 | return name .. " | " .. parameters_as_json .. "\n" .. output
1517 |
1518 | state:
1519 | path: ENV/NANO_BOTS_STATE_PATH
1520 |
1521 | safety:
1522 | functions:
1523 | sandboxed: true
1524 | tools:
1525 | confirmable: true
1526 |
1527 | provider:
1528 | id: openai
1529 | credentials:
1530 | address: ENV/OPENAI_API_ADDRESS
1531 | access-token: ENV/OPENAI_API_KEY
1532 | settings:
1533 | user: ENV/NANO_BOTS_END_USER
1534 | model: gpt-4o
1535 | stream: true
1536 | frequency_penalty: 0
1537 | logit_bias: null
1538 | logprobs: false
1539 | top_logprobs: null
1540 | max_tokens: null
1541 | n: 1
1542 | presence_penalty: 0
1543 | response_format:
1544 | type: json_object
1545 | seed: null
1546 | stop:
1547 | - .
1548 | temperature: 1
1549 | top_p: 1
1550 | tool_choice: auto
1551 |
1552 | provider:
1553 | id: google
1554 | credentials:
1555 | service: generative-language-api
1556 | api-key: ENV/GOOGLE_API_KEY
1557 | credentials:
1558 | service: vertex-ai-api
1559 | region: ENV/GOOGLE_REGION
1560 | credentials:
1561 | service: vertex-ai-api
1562 | region: ENV/GOOGLE_REGION
1563 | file-path: ENV/GOOGLE_CREDENTIALS_FILE_PATH
1564 | credentials:
1565 | service: vertex-ai-api
1566 | region: ENV/GOOGLE_REGION
1567 | file-path: ENV/GOOGLE_CREDENTIALS_FILE_PATH
1568 | project-id: ENV/GOOGLE_PROJECT_ID
1569 | options:
1570 | model: gemini-pro
1571 | stream: true
1572 | settings:
1573 | safetySettings:
1574 | - category: HARM_CATEGORY_DANGEROUS_CONTENT
1575 | threshold: BLOCK_NONE
1576 | generationConfig:
1577 | temperature: 0.9
1578 | maxOutputTokens: 8192
1579 | topK: null
1580 | topP: 1.0
1581 | stopSequences:
1582 | - .
1583 |
1584 | miscellaneous:
1585 | key: value
1586 | ```
1587 |
1588 | ## State
1589 |
1590 | ### Stateless
1591 |
1592 | By default, Nano Bots are stateless.
1593 |
1594 | An evaluation is a single-turn interaction.
1595 |
1596 | A REPL should be capable of maintaining multi-turn interactions, which means it must retain the conversation history and utilize it during interactions throughout its lifetime. Once the user exits the REPL, all history are discarded.
1597 |
1598 | The default stateless behavior is defined by the `-` character in interactions:
1599 |
1600 | ```bash
1601 | nb assistant.yml - repl
1602 | nb assistant.yml - eval "Hi"
1603 | ```
1604 |
1605 | ### Stateful
1606 |
1607 | Implementations should support storing state by identifying a state key different from `-`:
1608 |
1609 | ```bash
1610 | nb assistant.yml E15D repl
1611 | nb assistant.yml D9D6 eval "Hi"
1612 | ```
1613 |
1614 | In this example, both `E15D` and `D9D6` are distinct identifiers used to indicate which state key should be employed for storing and retrieving state information related to that interaction.
1615 |
1616 | In this scenario, both Eval and REPL store their states (history) and should be capable of performing multi-turn interactions. Eval should remember its previous interactions, and a REPL should remember its previous interactions even if it is exited and started again.
1617 |
1618 | By default, implementations should be [XDG compliant](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html), which means that the default storage path would be:
1619 |
1620 | ```text
1621 | /home/user/.local/state/nano-bots/your-implementation
1622 | ```
1623 |
1624 | If the `NANO_BOTS_STATE_PATH` environment variable exists, it should be used as the path to store the states.
1625 |
1626 | A Cartridge may include a section that defines a custom path for storing the states. In this case, it should override both the default and the path specified by the environment variable:
1627 |
1628 | ```yaml
1629 | ---
1630 | state:
1631 | path: ENV/NANO_BOTS_STATE_PATH
1632 | ```
1633 |
1634 | The state should be stored in a manner that ensures isolation between multiple Nano Bots and Implementations.
1635 |
1636 | In this example:
1637 |
1638 | ```bash
1639 | nb assistant.yml E15D repl
1640 | ```
1641 |
1642 | ```yaml
1643 | ---
1644 | meta:
1645 | symbol: 🤖
1646 | name: Nano Bot Name
1647 | author: Author Name
1648 | version: 1.0.0
1649 | license: CC0-1.0
1650 | description: A helpful assistant.
1651 |
1652 | state:
1653 | path: /home/user/.local/state/nano-bots
1654 |
1655 | provider:
1656 | settings:
1657 | user: end-user-name
1658 | ```
1659 |
1660 | The state should be stored in a path similar to this:
1661 |
1662 | ```text
1663 | /home/user/.local/state/nano-bots/your-implementation/author-name/nano-bot-name/0-0-1/end-user-name/E15D/state.json
1664 | ```
1665 |
1666 | If not specified in the provider settings, `end-user-name` should be loaded from the environment variable `NANO_BOTS_END_USER`. If the environment variable does not exist, use the default `unknown` value:
1667 |
1668 | ```text
1669 | /home/user/.local/state/nano-bots/your-implementation/author-name/nano-bot-name/0-0-1/unknown/E15D/state.json
1670 | ```
1671 |
1672 | JSON is merely an example; each implementation can choose the most suitable data format to work with.
1673 |
1674 | > ⚠️ A Nano Bot should **never** depend on or rely on a state to function fully—**absolutely never**.
1675 |
1676 | States serve as a convenience for users and should not be used to influence Nano Bot behaviors. Instead, such behaviors should be managed through the [Behaviors](?id=behaviors) section of the Cartridge YAML. This reinforces the notion that a Cartridge YAML file should ultimately be the sole and only necessary information for the bot to operate as expected.
1677 |
1678 | ## Stream
1679 |
1680 | Unless otherwise specified in the Cartridge file, or if not supported by the provider, both the REPL and Eval Interfaces should be capable of streaming messages. This means they should be able to display content partially, whether character by character, token by token, or word by word.
1681 |
1682 | # Breaking Changes
1683 |
1684 | ## 3.0.0
1685 |
1686 | From version `2.3.0` to version `3.0.0`:
1687 |
1688 | Cartridges must have a `.yml` or `.yaml` extension.
1689 |
1690 | `NANO_BOTS_STATE_DIRECTORY` has been renamed to `NANO_BOTS_STATE_PATH`.
1691 | `NANO_BOTS_CARTRIDGES_DIRECTORY` has been renamed to `NANO_BOTS_CARTRIDGES_PATH`.
1692 |
1693 | Although some implementations may offer backward compatibility for these changes, supporting the old names is not expected in version `3.0.0`.
1694 |
1695 | ## 2.0.0
1696 |
1697 | From version `1.1.0` to version `2.0.0`:
1698 |
1699 | Google Provider requires a new `service` key in `credentials`.
1700 |
1701 | ## 1.0.0
1702 |
1703 | From version `0.2.0` to version `1.0.0`:
1704 |
1705 | Lua functions should start to expect explicit `return` statements.
1706 |
1707 | Before:
1708 |
1709 | ```yaml
1710 | ---
1711 | lua: |
1712 | "```" .. content .. "```"
1713 | ```
1714 |
1715 | After:
1716 | ```yaml
1717 | ---
1718 | lua: |
1719 | return "```" .. content .. "```"
1720 | ```
1721 |
1722 | This decision was made to support complex multiline Lua functions. Without explicit `return` statements, implementations would need to infer where to inject the `return` statement to create valid Lua code, which could potentially compromise the functionality of the code through incorrect assumptions.
1723 |
1724 | # Experimental
1725 |
1726 | ## Clojure Support
1727 |
1728 | We are exploring the use of [Clojure](https://clojure.org) through [Babashka](https://babashka.org), powered by [GraalVM](https://www.graalvm.org).
1729 |
1730 | Currently, [Lua](https://www.lua.org/about.html) and [Fennel](https://fennel-lang.org) are our primary supported languages, due to their proven portability, widespread availability, lightweight nature, and ease of embedding. If this specific flavor of Clojure continues to demonstrate the potential to offer the same attributes as observed in Lua and Fennel, it may become an additional language that is expected to be supported in our specification. Regardless of this potential move, we have absolutely no intention of removing or replacing Lua or Fennel as the primary supported languages.
1731 |
1732 | The experimental support for Clojure would be similar to Lua and Fennel, using the `clojure:` key:
1733 |
1734 | ```yaml
1735 | ---
1736 | clojure: |
1737 | (-> (java.time.ZonedDateTime/now)
1738 | (.format (java.time.format.DateTimeFormatter/ofPattern "yyyy-MM-dd HH:mm"))
1739 | (clojure.string/trimr))
1740 | ```
1741 |
1742 | ## Markdown Support
1743 |
1744 | We are exploring the use of [Markdown](https://en.wikipedia.org/wiki/Markdown) as a cartridge source code format. The following file extensions become valid cartridges:
1745 |
1746 | ```text
1747 | .md .mkdn .mdown .markdown
1748 | ```
1749 |
1750 | This is an example of a Markdown cartridge:
1751 |
1752 | ````md
1753 | Start by defining a meta section:
1754 |
1755 | ```yaml
1756 | meta:
1757 | symbol: 🤖
1758 | name: Nano Bot Name
1759 | author: Your Name
1760 | description: A helpful assistant.
1761 | ```
1762 |
1763 | You can also add version and license information:
1764 |
1765 | ```yaml
1766 | meta:
1767 | version: 1.0.0
1768 | license: CC0-1.0
1769 | ```
1770 |
1771 | Then, add a behavior section:
1772 |
1773 | ```yaml
1774 | behaviors:
1775 | interaction:
1776 | directive: You are a helpful assistant.
1777 | ```
1778 | ````
1779 |
1780 | Implementations should extract each code block and merge them to end up with the complete cartridge's source code, ignoring everything else:
1781 |
1782 | ```yaml
1783 | ---
1784 | meta:
1785 | symbol: 🤖
1786 | name: Nano Bot Name
1787 | author: Your Name
1788 | description: A helpful assistant.
1789 | version: 1.0.0
1790 | license: CC0-1.0
1791 | behaviors:
1792 | interaction:
1793 | directive: You are a helpful assistant.
1794 | ```
1795 |
1796 | Code blocks in supported languages that appear after a previous tool's definition should be incorporated as the function source code of the last defined tool:
1797 |
1798 |
1799 | ````md
1800 | This is the specification of the tool:
1801 |
1802 | ```yaml
1803 | tools:
1804 | - name: date-and-time
1805 | description: Returns the current date and time.
1806 | ```
1807 |
1808 | This is the function source code for the tool:
1809 |
1810 | ```fnl
1811 | (os.date)
1812 | ```
1813 | ````
1814 |
1815 | The above Markdown cartridge should be extracted as:
1816 | ```yaml
1817 | ---
1818 | tools:
1819 | - name: date-and-time
1820 | description: Returns the current date and time.
1821 | fennel: |
1822 | (os.date)
1823 | ```
1824 |
1825 | Root keys that are array values should be concatenated:
1826 |
1827 | ````md
1828 | This is the first tool:
1829 |
1830 | ```yaml
1831 | tools:
1832 | - name: date-and-time
1833 | description: Returns the current date and time.
1834 | ```
1835 |
1836 | That has this source code:
1837 |
1838 | ```fnl
1839 | (os.date)
1840 | ```
1841 |
1842 | This is the second tool:
1843 |
1844 | ```yaml
1845 | tools:
1846 | - name: random-number
1847 | description: Generates a random number.
1848 | ```
1849 |
1850 | With this source code:
1851 |
1852 | ```lua
1853 | return math.random()
1854 | ```
1855 |
1856 | ````
1857 |
1858 | The above Markdown cartridge should be extracted as:
1859 |
1860 | ```yaml
1861 | ---
1862 | tools:
1863 | - name: date-and-time
1864 | description: Returns the current date and time.
1865 | fennel: |
1866 | (os.date)
1867 | - name: random-number
1868 | description: Generates a random number.
1869 | lua: |
1870 | return math.random()
1871 | ```
1872 |
--------------------------------------------------------------------------------
/docs/cover.md:
--------------------------------------------------------------------------------
1 | # 🤖
2 | # Nano Bots
3 |
4 | > Specification for AI powered Nano Bots.
5 |
6 | - Unlock the remarkable capabilities of AI.
7 | - Quickly create intelligent bots in seconds.
8 | - Effortlessly integrate multiple bots to achieve your goals.
9 | - Share your Nano Bots and enable others to benefit from their abilities.
10 |
11 | Version 3.2.0
12 |
13 | [Specification](README)
14 | [GitHub](https://github.com/icebaker/nano-bots-spec)
15 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |