Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions cozy.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ jobs:
# - "service": launching services
# - "migrations": transforming a VFS with Swift to layout v3
# - "notes-save": saving notes to the VFS
# - "rag-index": send data to the RAG server for being indexed
# - "rag-query": send a query to the RAG server
# - "push": sending push notifications
# - "sms": sending SMS notifications
# - "sendmail": sending mails
Expand Down Expand Up @@ -200,6 +202,15 @@ konnectors:
# cmd: ./scripts/konnector-rkt-run.sh # run connectors with rkt
# cmd: ./scripts/konnector-nsjail-node8-run.sh # run connectors with nsjail

# rag are the URL of the RAG server(s) for AI.
rag:
# A cozy will use the rag server for its context, or if the context is not
# declared, for default.
default:
url: http://localhost:8000
beta:
url: http://localhost:8001

# mail service parameters for sending email via SMTP
mail:
# mail noreply address - flags: --mail-noreply-address
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ designing new services.

### List of services

- `/ai` - [AI](ai.md)
- `/auth` - [Authentication & OAuth](auth.md)
- [Delegated authentication](delegated-auth.md)
- `/apps` - [Applications Management](apps.md)
Expand Down
112 changes: 112 additions & 0 deletions docs/ai.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
[Table of contents](README.md#table-of-contents)

# AI for personal data

## Introduction

AI can be used for interacting with the personal data of a Cozy. This is
currently an experimental feature. Retrieval-Augmented Generation (RAG) is
a classical pattern in the AI world. Here, it is specific to each Cozy.

![Architecture with a RAG server](diagrams/ai.svg)

## Indexation

First of all, the RAG server must be installed with its dependencies. It is
not mandatory to install them on the same servers as the cozy-stack. And the
URL of RAG must be filled in cozy-stack configuration file (in `rag`).

For the moment, the feature is experimental, and a trigger must be created
manually on the Cozy:

```sh
$ COZY=cozy.localhost:8080
$ TOKEN=$(cozy-stack instances token-cli $COZY io.cozy.triggers)
$ curl "http://${COZY}/jobs/triggers" -H "Authorization: Bearer $TOKEN" -d '{ "data": { "attributes": { "type": "@event", "arguments": "io.cozy.files", "debounce": "1m", "worker": "rag-index", "message": {"doctype": "io.cozy.files"} } } }'
```

It can also be a good idea to start a first indexation with:

```sh
$ cozy-stack triggers launch --domain $COZY $TRIGGER_ID
```

In practice, when files are uploaded/modified/deleted, the trigger will create
a job for the index worker (with debounce). The index worker will look at the
changed feed, and will call the RAG for each entry in the changes feed.

## Chat

When a user starts a chat, their prompts are sent to the RAG that can use the
vector database to find relevant documents (technically, only some parts of
the documents called chunks). Those documents are added to the prompt, so
that the LLM can use them as a context when answering.

### POST /ai/chat/completions/:id

This route can be used to ask AI for a chat completion. The id in the path
must be the identifier of a chat session. The client can generate a random
identifier for a new chat session.

The stack will respond after pushing a job for this task, but without the
response. The client must use the real-time websocket and subscribe to
`io.cozy.ai.chat.events`.

#### Request

```http
POST /ai/chat/completions/e21dce8058b9013d800a18c04daba326 HTTP/1.1
Content-Type: application/json
```

```json
{
"q": "Why the sky is blue?"
}
```

#### Response

```http
HTTP/1.1 202 Accepted
Content-Type: application/vnd.api+json
```

```json
{
"data": {
"type": "io.cozy.ai.chat.completions"
"id": "e21dce8058b9013d800a18c04daba326",
"rev": "1-23456",
"attributes": {
"messages": [
{
"role": "user",
"content": "Why the sky is blue?"
}
]
}
}
}
```

### Real-time via websockets

```
client > {"method": "AUTH", "payload": "token"}
client > {"method": "SUBSCRIBE",
"payload": {"type": "io.cozy.ai.chat.events"}}
server > {"event": "CREATED",
"payload": {"id": "e21dce8058b9013d800a18c04daba326",
"type": "io.cozy.ai.chat.events",
"doc": {"object": "delta", "content": "The "}}}
server > {"event": "CREATED",
"payload": {"id": "e21dce8058b9013d800a18c04daba326",
"type": "io.cozy.ai.chat.events",
"doc": {"object": "delta", "content": "sky "}}}
[...]
server > {"event": "CREATED",
"payload": {"id": "e21dce8058b9013d800a18c04daba326",
"type": "io.cozy.ai.chat.events",
"doc": {"object": "done"}}}
```
17 changes: 17 additions & 0 deletions docs/diagrams/ai.d2
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# https://d2lang.com/

stack: {label: "Cozy-Stack"}
rag: {label: "RAG"}
llm: {label: "LLM"; shape: diamond}
embed: {label: "Embeddings model"; shape: diamond}
vector: {label: "Vector DB"; shape: cylinder}
couchdb: {label: "CouchDB"; shape: cylinder}
swift: {label: "Swift"; shape: cylinder}

stack -> rag
stack -> couchdb
stack -> swift

rag -> embed
rag -> vector
rag -> llm
101 changes: 101 additions & 0 deletions docs/diagrams/ai.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
- "Sharing design": ./sharing-design.md
- "Workflow of the konnectors": ./konnectors-workflow.md
- List of services:
- "/ai - AI": ./ai.md
- "/auth - Authentication & OAuth": ./auth.md
- " /oidc - Delegated authentication": ./delegated-auth.md
- "/apps - Applications Management": ./apps.md
Expand Down
6 changes: 6 additions & 0 deletions docs/workers.md
Original file line number Diff line number Diff line change
Expand Up @@ -412,3 +412,9 @@ It can be launched from command-line with:
```sh
$ cozy-stack jobs run migrations --domain example.mycozy.cloud --json '{"type": "to-swift-v3"}'
```

## index

This worker is used for sending data to a RAG. It looks at the changes feed for
the given doctype, send the changes to an external indexer that will generate
embeddings for the data and put them in a vector database.
11 changes: 11 additions & 0 deletions model/instance/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,17 @@ func (i *Instance) Registries() []*url.URL {
return context
}

// RAGServer returns the RAG server for the instance (AI features).
func (i *Instance) RAGServer() config.RAGServer {
contexts := config.GetConfig().RAGServers
if i.ContextName != "" {
if server, ok := contexts[i.ContextName]; ok {
return server
}
}
return contexts[config.DefaultInstanceContext]
}

// HasForcedOIDC returns true only if the instance is in a context where the
// config says that the stack shouldn't allow to authenticate with the
// password.
Expand Down
Loading
Loading