Skip to content
This repository has been archived by the owner on Jul 1, 2024. It is now read-only.

Commit

Permalink
Sun Apr 21 17:00:34 PDT 2024
Browse files Browse the repository at this point in the history
  • Loading branch information
0x77dev committed Apr 22, 2024
1 parent e888549 commit c255e1f
Show file tree
Hide file tree
Showing 24 changed files with 103 additions and 11 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ For documentation, visit the project website: [ava.0x77.dev](https://ava.0x77.de

- **Supports major LLMs**: OpenAI, Anthropic, and Ollama supported by default.
- **Home Assistant Integration**: Control Home Assistant devices and get entity information.
- **Extensible _(work in progress)_**: Easily add new skills via custom HTTP endpoints.
- **Extensible _(work in progress)_**: Easily add new skill via custom HTTP endpoints.
- **Customizable**: Highly configurable through environment variables.
- **Fully private**: Can be self-hosted for complete data control.
- **OpenAI compatible endpoints**: Chat with Ava using OpenAI-compatible chat completion.
Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/content/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ features:
target: '_blank'
- title: 'Extensible'
wip: true
description: 'Easily add new skills via custom HTTP endpoints'
description: 'Easily add new skill via custom HTTP endpoints'
icon: 'i-heroicons-sparkles-20-solid'
target: '_blank'
- title: 'Customizable'
Expand Down
1 change: 1 addition & 0 deletions ollama/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ports:
image: docker.io/ollama/ollama
ingress: true
ingress_port: 11434
ingress_stream: true
map:
- config:rw
environment:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"license": "GPL-3.0",
"workspaces": [
"packages/*",
"skills/*",
"skill/*",
"docs",
"server"
],
Expand Down
15 changes: 11 additions & 4 deletions server/config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: "Ava Server"
description: "Self-hosted personal assistant in minutes with built-in Home Assistant integration and great extensibility and customizability"
version: "edge"
version: "0.0.0"
slug: "server"
init: false
arch:
Expand All @@ -13,6 +13,7 @@ image: ghcr.io/0x77dev/ava/server
homeassistant_api: true
ingress: true
ingress_port: 2881
ingress_stream: true
options:
llm:
namespace: anthropic
Expand All @@ -21,15 +22,21 @@ options:
embeddings:
namespace: ollama
baseURL: "http://04c4e5a1-ollama:11434"
name: nomic-embed-text
name: snowflake-arctic-embed:22m
skills: []
schema:
llm:
namespace: str
namespace: list(anthropic|openai|ollama)
name: "str"
token: "str?"
baseURL: "str?"
embeddings:
namespace: str
namespace: list(openai|ollama)
name: "str"
token: "str?"
baseURL: "str?"
skills:
- name: "str"
description: "str"
returnDirect: "bool?"
url: "str"
3 changes: 2 additions & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"dependencies": {
"@ava/lang": "workspace:../packages/lang",
"@ava/oai-types": "workspace:../packages/oai-types",
"@ava/skills-homeassistant": "workspace:../packages/skills-homeassistant",
"@ava/skill-homeassistant": "workspace:../skill/homeassistant",
"@ava/skill-dynamic": "workspace:../skill/dynamic",
"@bogeychan/elysia-logger": "^0.0.21",
"@elysiajs/swagger": "^1.0.3",
"elysia": "latest",
Expand Down
4 changes: 4 additions & 0 deletions server/src/addon-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ export const injectHassOptions = async () => {
process.env.EMBEDDINGS = JSON.stringify(options.embeddings)
}

if (options.skills) {
process.env.SKILLS = JSON.stringify(options.skills)
}

if (process.env.SUPERVISOR_TOKEN) {
process.env.HOMEASSISTANT = JSON.stringify({
"token": process.env.SUPERVISOR_TOKEN,
Expand Down
7 changes: 6 additions & 1 deletion server/src/services/assistant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@ export const getAssistant = async () => {
const tools: ToolInterface[] = []

if (process.env.HOMEASSISTANT) {
const { createHomeAssistantToolkit } = await import('@ava/skills-homeassistant')
const { createHomeAssistantToolkit } = await import('@ava/skill-homeassistant')
tools.push(...await createHomeAssistantToolkit())
}

if (process.env.SKILLS) {
const { createDynamicToolkit } = await import('@ava/skill-dynamic')
tools.push(...await createDynamicToolkit())
}

assistant = await createAssistant(tools)
return assistant
}
9 changes: 9 additions & 0 deletions skill/dynamic/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { parseEnv, z } from "znv";
import { SkillListSchema } from "./schema";

export const { SKILLS } = parseEnv(process.env, {
SKILLS: {
schema: z.string().transform((value) => SkillListSchema.parse(JSON.parse(value))),
description: "Skills configuration"
}
})
23 changes: 23 additions & 0 deletions skill/dynamic/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { DynamicTool, type ToolInterface } from '@ava/lang'
import { SKILLS } from './config'
import { http } from './provider/http'

export const createDynamicToolkit = async (): Promise<ToolInterface[]> => {
return SKILLS.map((skill) => {
console.info(`[Dynamic Skill] creating dynamic tool for ${skill.name} at ${skill.url}`)

return new DynamicTool({
name: skill.name,
description: skill.description,
returnDirect: skill.returnDirect,
async func(body) {
const response = await http.post(skill.url, {
body,
responseType: 'json'
}).text()

return response
}
})
})
}
18 changes: 18 additions & 0 deletions skill/dynamic/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "@ava/skill-dynamic",
"module": "index.ts",
"type": "module",
"version": "0.0.0",
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
},
"dependencies": {
"@ava/lang": "workspace:../../packages/lang",
"got": "^14.2.1",
"znv": "^0.4.0",
"zod": "^3.23.0"
}
}
8 changes: 8 additions & 0 deletions skill/dynamic/provider/http.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import got from "got"
import { version } from "../package.json"

export const http = got.extend({
headers: {
"User-Agent": `ava-dynamic-skill/${version}`,
}
})
13 changes: 13 additions & 0 deletions skill/dynamic/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { z } from "zod";

export const SkillSchema = z.object({
name: z.string(),
description: z.string(),
// schema: z.optional(z.any()).describe('JSON schema if the skill requires input'),
returnDirect: z.boolean().optional().describe('Whether the skill returns the result directly or not').default(false),
url: z.string().url().describe('HTTP POST URL to send the data to'),
})
export type Skill = z.infer<typeof SkillSchema>

export const SkillListSchema = z.array(SkillSchema)
export type SkillList = z.infer<typeof SkillListSchema>
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@ava/skills-homeassistant",
"name": "@ava/skill-homeassistant",
"module": "index.ts",
"type": "module",
"dependencies": {
Expand All @@ -15,4 +15,4 @@
"peerDependencies": {
"typescript": "^5.0.0"
}
}
}
File renamed without changes.
3 changes: 3 additions & 0 deletions skill/homeassistant/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../../tsconfig.json"
}

0 comments on commit c255e1f

Please sign in to comment.