Skip to content

Commit 180a1e7

Browse files
author
Daniele Briggi
committed
feat(readme): add readme with edge fn template
1 parent fb512b4 commit 180a1e7

File tree

4 files changed

+219
-7
lines changed

4 files changed

+219
-7
lines changed

.github/workflows/test.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,5 @@ jobs:
1717
connection_string: ${{ secrets.CONNECTION_STRING }}
1818
base_url: https://docs.sqlitecloud.io/docs/
1919
database_name: aisearch-action-test.sqlite
20-
database_path: sqliterag.sqlite
2120
# only few files for testing
2221
source_files: docs/sqlite-cloud/sdks/php

README.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
[<img src="https://github.com/user-attachments/assets/0d406c41-ff61-41d7-a8de-249e9e652946" alt="https://sqlite.ai" width="110"/>](https://sqlite.ai)
2+
3+
# SQLite AI Search Action
4+
5+
Index your documentation files with SQLite AI-powered embeddings for intelligent search capabilities.
6+
7+
[![Test](https://github.com/sqliteai/sqlite-aisearch-action/actions/workflows/test.yaml/badge.svg?branch=main)](https://github.com/sqliteai/sqlite-aisearch-action/actions/workflows/test.yaml)
8+
[![GitHub Release](https://img.shields.io/github/v/release/sqliteai/sqlite-aisearch-action?label=Version)](https://github.com/sqliteai/sqlite-aisearch-action/releases/latest)
9+
10+
## Overview
11+
12+
The SQLite AI Search Action automatically processes your documentation files and creates an AI-powered searchable database on SQLite Cloud. This action uses both embeddings to understand document content semantically and traditional full-text search, enabling more intelligent and contextual search results.
13+
14+
This action uses [sqlite-rag](https://github.com/sqliteai/sqlite-rag).
15+
16+
## How it works
17+
18+
1. **Downloads AI Model**: Retrieves the specified Hugging Face model to generate embeddings for semantic search
19+
2. **Processes Documents**: Recursively scans and parses all documentation files in your repository
20+
3. **Creates Dual Index**: Generates both AI embeddings and traditional full-text search indices for comprehensive search capabilities
21+
4. **Builds Database**: Creates a SQLite database containing documents, embeddings, and search indices
22+
5. **Uploads to SQLite Cloud**: Transfers the complete database to your SQLite Cloud project
23+
6. **Integrates with Edge Function**: Works out-of-the-box with the predefined SQLite Cloud Edge Function template ([aisearch-docs.js](search_edge_function_template/aisearch-docs.js)) for instant search functionality
24+
25+
> **Note**: the SQLite Cloud Search Edge Function supports only the default model. Do not change the model settings if you want to use our search edge function.
26+
27+
## Usage
28+
29+
### Setup your workflow
30+
31+
1. **Get your Connection String**: Ensure you have a project on [SQLite Cloud dashboard](https://dashboard.sqlitecloud.io). If not, sign up to [SQLite AI](https://sqlite.ai) to create one for free.
32+
33+
2. **Set GitHub Secret**: Add your connection string as `SQLITECLOUD_CONNECTION_STRING` in your repository secrets.
34+
35+
3. **Add to Workflow**: Create or update your GitHub workflow:
36+
37+
```yaml
38+
name: AI Search Index
39+
40+
on:
41+
push:
42+
branches: [main]
43+
workflow_dispatch:
44+
45+
jobs:
46+
build-search:
47+
runs-on: ubuntu-latest
48+
steps:
49+
- uses: actions/checkout@v4
50+
51+
- name: Build AI Search Database
52+
uses: sqliteai/sqlite-aisearch-action@v1
53+
with:
54+
connection_string: ${{ secrets.SQLITECLOUD_CONNECTION_STRING }}
55+
base_url: https://docs.yoursite.com
56+
database_name: aidocs_search.db
57+
source_files: ./path/to/documents
58+
```
59+
60+
### Create the Search Edge Function
61+
62+
To enable search functionality on your indexed database, you need to create an Edge Function using the provided template:
63+
64+
1. Access your dashboard on https://dashboard.sqlitecloud.io
65+
2. Enter the same project where the created database has been uploaded
66+
3. Go to the **Edge Functions** section
67+
4. Create a new `Javascript Function` and copy and paste the code from [aisearch-docs.js](search_edge_function_template/aisearch-docs.js) in the editor
68+
5. Deploy and test
69+
70+
#### How to perform a search
71+
72+
1. Go in the **Detail** in the Edge Function panel and copy the **Function URL**
73+
2. Execute a GET request and send a URL-econded query as `query` parameter.
74+
75+
Example: `GET
76+
https://myproject.cloud/v2/functions/aisearch-docs?query=what%27s+Offsync%3F`
77+
78+
Response example:
79+
```json
80+
{
81+
"data": {
82+
"search": [
83+
{
84+
"id": "c41a6c2e-34e9-4e8e-92b9-41b8065047c7",
85+
"uri": "docs/sqlite-cloud/sdks/php/methods.mdx",
86+
"metadata": "{\"base_url\": \"https://docs.sqlitecloud.io/docs/\"}",
87+
"snippet": "---\ntitle: OffSync\ndescription: Enable local-first applications with automatic data synchronization between edge devices and SQLite Cloud...",
88+
"vec_rank": 1,
89+
"fts_rank": null,
90+
"combined_rank": 0.0163934426229508,
91+
"vec_distance": 0.581515073776245,
92+
"fts_score": null
93+
},
94+
...
95+
]
96+
}
97+
}
98+
```
99+
100+
## Support
101+
102+
- 📖 [SQLite Cloud Documentation](https://docs.sqlitecloud.io)
103+
- 💬 [Community Support](https://github.com/orgs/sqlitecloud/discussions)

action.yaml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: "SQLite AI - AI search for documents"
2-
description: "Parses document files to create a database on your SQLite Cloud project."
2+
description: "Out-of-the-box database for AI search for documents powered by SQLite AI."
33
author: "SQLite AI Team"
44

55
inputs:
@@ -12,9 +12,6 @@ inputs:
1212
database_name:
1313
description: The name of the database to use on SQLite Cloud
1414
required: true
15-
database_path:
16-
description: The local path of the database file to upload to SQLite Cloud.
17-
required: true
1815
source_files:
1916
description: The path of the files, by default it will parse every file recursively starting from the working directory.
2017
required: false
@@ -81,14 +78,16 @@ runs:
8178
run: |
8279
sqlite-rag add \
8380
--recursive "${{ inputs.source_files }}" \
84-
--metadata '{"base_url": "${{ inputs.base_url }}"}'
81+
--metadata '{"base_url": "${{ inputs.base_url }}"}' \
82+
--relative-paths
8583
shell: bash
8684

8785
- name: Upload the database to SQLite Cloud
8886
run: bash $GITHUB_ACTION_PATH/upload.sh
8987
env:
9088
GITHUB_ACTION_PATH: ${{ github.action_path }}
9189
CONNECTION_STRING: ${{ inputs.connection_string }}
92-
DATABASE_PATH: ${{ inputs.database_path }}
90+
# default sqlite-rag database path
91+
DATABASE_PATH: "./sqliterag.sqlite"
9392
DATABASE: ${{ inputs.database_name }}
9493
shell: bash
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/**
2+
* Edge Function template for performing AI-powered search on databases created by the GitHub Action.
3+
*
4+
* This template provides a ready-to-use Edge Function that users can copy and paste
5+
* into their SQLite Cloud project to enable semantic search capabilities on the
6+
* documentation database generated by the sqlite-aisearch-action GitHub Action.
7+
*
8+
* The function combines vector embeddings with full-text search using Reciprocal
9+
* Rank Fusion (RRF) to deliver accurate and contextually relevant search results.
10+
*
11+
* See README.md for deployment instructions.
12+
*/
13+
14+
//---- CONFIGURATION ----
15+
const sqliteAIBaseUrl = "https://aiserver.vital-rhino.eks.euc1.ryujaz.sqlite.cloud";
16+
const sqliteAIAPI = "/v1/ai/embeddings"
17+
//-----------------------
18+
19+
const requestid = request.params.requestid;
20+
const query = request.params.query;
21+
22+
// get embedding from sqlite-ai-server
23+
const data = {"text": query };
24+
const response = await fetch(sqliteAIBaseUrl + sqliteAIAPI, {
25+
method: "POST",
26+
headers: {
27+
"Content-Type": "application/json"
28+
},
29+
body: JSON.stringify(data)
30+
});
31+
32+
if (!response.ok) {
33+
throw new Error("Failed to generate embedding. " + response.statusText);
34+
}
35+
36+
const result = await response.json();
37+
const query_embedding = result.data.embedding;
38+
39+
// clean query for full-text search
40+
const query_fts = (query.toLowerCase().match(/\b\w+\b/g) || []).join(" ") + "*";
41+
42+
// --- TEST ---
43+
//const test_embedding = await connection.sql('SELECT embedding FROM chunks LIMIT 1;');
44+
//const query_embedding = test_embedding[0].embedding;
45+
// ------------
46+
47+
// Vector configuration must match the embedding parameters used during database generation
48+
await connection.sql("SELECT vector_init('chunks', 'embedding', 'type=INT8,dimension=768,distance=cosine')");
49+
50+
const res = await connection.sql(
51+
`
52+
-- sqlite-vector KNN vector search results
53+
WITH vec_matches AS (
54+
SELECT
55+
v.rowid AS chunk_id,
56+
row_number() OVER (ORDER BY v.distance) AS rank_number,
57+
v.distance
58+
FROM vector_quantize_scan('chunks', 'embedding', ?, 10) AS v
59+
),
60+
-- Full-text search results
61+
fts_matches AS (
62+
SELECT
63+
chunks_fts.rowid AS chunk_id,
64+
row_number() OVER (ORDER BY rank) AS rank_number,
65+
rank AS score
66+
FROM chunks_fts
67+
WHERE chunks_fts MATCH ?
68+
LIMIT 10
69+
),
70+
-- combine FTS5 + vector search results with RRF
71+
matches AS (
72+
SELECT
73+
COALESCE(vec_matches.chunk_id, fts_matches.chunk_id) AS chunk_id,
74+
vec_matches.rank_number AS vec_rank,
75+
fts_matches.rank_number AS fts_rank,
76+
-- Reciprocal Rank Fusion score
77+
(
78+
COALESCE(1.0 / (60 + vec_matches.rank_number), 0.0) * 1.0 +
79+
COALESCE(1.0 / (60 + fts_matches.rank_number), 0.0) * 1.0
80+
) AS combined_rank,
81+
vec_matches.distance AS vec_distance,
82+
fts_matches.score AS fts_score
83+
FROM vec_matches
84+
FULL OUTER JOIN fts_matches
85+
ON vec_matches.chunk_id = fts_matches.chunk_id
86+
)
87+
SELECT
88+
documents.id,
89+
documents.uri,
90+
documents.content as document_content,
91+
documents.metadata,
92+
chunks.content AS snippet,
93+
vec_rank,
94+
fts_rank,
95+
combined_rank,
96+
vec_distance,
97+
fts_score
98+
FROM matches
99+
JOIN chunks ON chunks.id = matches.chunk_id
100+
JOIN documents ON documents.id = chunks.document_id
101+
ORDER BY combined_rank DESC
102+
;
103+
`, query_embedding, query_fts)
104+
105+
106+
return {
107+
data: {
108+
search: res,
109+
requestid: requestid
110+
}
111+
}

0 commit comments

Comments
 (0)