Skip to content

Commit 6410136

Browse files
committed
feat: add support for customizable server-side prompts
- **Custom Prompt Templates**: Introduced support for user-modifiable prompt templates using Go's `text/template`. - Added default prompt templates for title and tag generation. - Templates are stored in the `prompts` directory and are loaded at startup. - If the template files do not exist, they are created with default content. - Users can modify the templates by editing the files in the `prompts` directory. - **API Endpoints for Prompts**: - Added `GET /api/prompts` endpoint to retrieve the current prompt templates. - Added `POST /api/prompts` endpoint to update the prompt templates. - These endpoints prepare for future UI support for modifying prompts. - **Thread Safety**: - Implemented a `sync.RWMutex` to ensure thread-safe access to the templates. - **Updated Backend Logic**: - Modified `getSuggestedTitle` and `getSuggestedTags` functions to use the loaded templates. - Templates utilize variables like `{{.Language}}`, `{{.Content}}`, `{{.AvailableTags}}`, and `{{.Title}}`. - **Docker and Documentation**: - Updated the `loadTemplates` function to ensure the `prompts` directory exists and to save default templates if missing. - Updated the README with instructions on how to mount the `prompts` directory in Docker and Docker Compose. - Provided guidance on modifying the prompt templates via file edits.
1 parent 0dd1d0b commit 6410136

File tree

7 files changed

+429
-93
lines changed

7 files changed

+429
-93
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.env
22
.DS_Store
3+
prompts/

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ RUN go mod download
1414
COPY . .
1515

1616
# Build the Go binary
17-
RUN CGO_ENABLED=0 GOOS=linux go build -o paperless-gpt main.go
17+
RUN CGO_ENABLED=0 GOOS=linux go build -o paperless-gpt .
1818

1919
# Stage 2: Build Vite frontend
2020
FROM node:20 AS frontend

README.md

+130-15
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55

66
![Screenshot](./paperless-gpt-screenshot.png)
77

8-
**paperless-gpt** is a tool designed to generate accurate and meaningful document titles for [paperless-ngx](https://github.com/paperless-ngx/paperless-ngx) using Large Language Models (LLMs). It supports multiple LLM providers, including **OpenAI** and **Ollama**. With paperless-gpt, you can streamline your document management by automatically suggesting appropriate titles and tags based on the content of your scanned documents.
8+
**paperless-gpt** is a tool designed to generate accurate and meaningful document titles and tags for [paperless-ngx](https://github.com/paperless-ngx/paperless-ngx) using Large Language Models (LLMs). It supports multiple LLM providers, including **OpenAI** and **Ollama**. With paperless-gpt, you can streamline your document management by automatically suggesting appropriate titles and tags based on the content of your scanned documents.
99

1010
[![Demo](./demo.gif)](./demo.gif)
1111

1212
## Features
1313

14-
- **Multiple LLM Support**: Choose between OpenAI and Ollama for generating document titles.
14+
- **Multiple LLM Support**: Choose between OpenAI and Ollama for generating document titles and tags.
15+
- **Customizable Prompts**: Modify the prompt templates to suit your specific needs.
1516
- **Easy Integration**: Works seamlessly with your existing paperless-ngx setup.
16-
- **User-Friendly Interface**: Intuitive web interface for reviewing and applying suggested titles.
17+
- **User-Friendly Interface**: Intuitive web interface for reviewing and applying suggested titles and tags.
1718
- **Dockerized Deployment**: Simple setup using Docker and Docker Compose.
1819

1920
## Table of Contents
@@ -28,6 +29,11 @@
2829
- [Manual Setup](#manual-setup)
2930
- [Configuration](#configuration)
3031
- [Environment Variables](#environment-variables)
32+
- [Custom Prompt Templates](#custom-prompt-templates)
33+
- [Prompt Templates Directory](#prompt-templates-directory)
34+
- [Mounting the Prompts Directory](#mounting-the-prompts-directory)
35+
- [Editing the Prompt Templates](#editing-the-prompt-templates)
36+
- [Template Syntax and Variables](#template-syntax-and-variables)
3137
- [Usage](#usage)
3238
- [Contributing](#contributing)
3339
- [License](#license)
@@ -64,7 +70,9 @@ services:
6470
LLM_MODEL: 'gpt-4o' # or 'llama2'
6571
OPENAI_API_KEY: 'your_openai_api_key' # Required if using OpenAI
6672
LLM_LANGUAGE: 'English' # Optional, default is 'English'
67-
OLLAMA_HOST: http://host.docker.internal:11434 # Useful if using Ollama
73+
OLLAMA_HOST: 'http://host.docker.internal:11434' # If using Ollama
74+
volumes:
75+
- ./prompts:/app/prompts # Mount the prompts directory
6876
ports:
6977
- '8080:8080'
7078
depends_on:
@@ -84,13 +92,19 @@ If you prefer to run the application manually:
8492
cd paperless-gpt
8593
```
8694

87-
2. **Build the Docker Image:**
95+
2. **Create a `prompts` Directory:**
96+
97+
```bash
98+
mkdir prompts
99+
```
100+
101+
3. **Build the Docker Image:**
88102

89103
```bash
90104
docker build -t paperless-gpt .
91105
```
92106

93-
3. **Run the Container:**
107+
4. **Run the Container:**
94108

95109
```bash
96110
docker run -d \
@@ -100,6 +114,7 @@ If you prefer to run the application manually:
100114
-e LLM_MODEL='gpt-4o' \
101115
-e OPENAI_API_KEY='your_openai_api_key' \
102116
-e LLM_LANGUAGE='English' \
117+
-v $(pwd)/prompts:/app/prompts \ # Mount the prompts directory
103118
-p 8080:8080 \
104119
paperless-gpt
105120
```
@@ -108,18 +123,118 @@ If you prefer to run the application manually:
108123

109124
### Environment Variables
110125

111-
| Variable | Description | Required |
112-
|-----------------------|-----------------------------------------------------------------------------------------------------|----------|
113-
| `PAPERLESS_BASE_URL` | The base URL of your paperless-ngx instance (e.g., `http://paperless-ngx:8000`). | Yes |
114-
| `PAPERLESS_API_TOKEN` | API token for accessing paperless-ngx. You can generate one in the paperless-ngx admin interface. | Yes |
115-
| `LLM_PROVIDER` | The LLM provider to use (`openai` or `ollama`). | Yes |
116-
| `LLM_MODEL` | The model name to use (e.g., `gpt-4`, `gpt-3.5-turbo`, `llama2`). | Yes |
117-
| `OPENAI_API_KEY` | Your OpenAI API key. Required if using OpenAI as the LLM provider. | Cond. |
118-
| `LLM_LANGUAGE` | The likely language of your documents (e.g., `English`, `German`). Default is `English`. | No |
119-
| `OLLAMA_HOST` | The URL of the Ollama server (e.g., `http://host.docker.internal:11434`). Useful if using Ollama. Default is `http://127.0.0.1:11434` | No |
126+
| Variable | Description | Required |
127+
|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|----------|
128+
| `PAPERLESS_BASE_URL` | The base URL of your paperless-ngx instance (e.g., `http://paperless-ngx:8000`). | Yes |
129+
| `PAPERLESS_API_TOKEN` | API token for accessing paperless-ngx. You can generate one in the paperless-ngx admin interface. | Yes |
130+
| `LLM_PROVIDER` | The LLM provider to use (`openai` or `ollama`). | Yes |
131+
| `LLM_MODEL` | The model name to use (e.g., `gpt-4o`, `gpt-3.5-turbo`, `llama2`). | Yes |
132+
| `OPENAI_API_KEY` | Your OpenAI API key. Required if using OpenAI as the LLM provider. | Cond. |
133+
| `LLM_LANGUAGE` | The likely language of your documents (e.g., `English`, `German`). Default is `English`. | No |
134+
| `OLLAMA_HOST` | The URL of the Ollama server (e.g., `http://host.docker.internal:11434`). Useful if using Ollama. Default is `http://127.0.0.1:11434`. | No |
120135

121136
**Note:** When using Ollama, ensure that the Ollama server is running and accessible from the paperless-gpt container.
122137

138+
### Custom Prompt Templates
139+
140+
You can customize the prompt templates used by paperless-gpt to generate titles and tags. By default, the application uses built-in templates, but you can modify them by editing the template files.
141+
142+
#### Prompt Templates Directory
143+
144+
The prompt templates are stored in the `prompts` directory inside the application. The two main template files are:
145+
146+
- `title_prompt.tmpl`: Template used for generating document titles.
147+
- `tag_prompt.tmpl`: Template used for generating document tags.
148+
149+
#### Mounting the Prompts Directory
150+
151+
To modify the prompt templates, you need to mount a local `prompts` directory into the container.
152+
153+
**Docker Compose Example:**
154+
155+
```yaml
156+
services:
157+
paperless-gpt:
158+
image: icereed/paperless-gpt:latest
159+
# ... (other configurations)
160+
volumes:
161+
- ./prompts:/app/prompts # Mount the prompts directory
162+
```
163+
164+
**Docker Run Command Example:**
165+
166+
```bash
167+
docker run -d \
168+
# ... (other configurations)
169+
-v $(pwd)/prompts:/app/prompts \
170+
paperless-gpt
171+
```
172+
173+
#### Editing the Prompt Templates
174+
175+
1. **Start the Container:**
176+
177+
When you first start the container with the `prompts` directory mounted, it will automatically create the default template files in your local `prompts` directory if they do not exist.
178+
179+
2. **Edit the Template Files:**
180+
181+
- Open `prompts/title_prompt.tmpl` and `prompts/tag_prompt.tmpl` with your favorite text editor.
182+
- Modify the templates using Go's `text/template` syntax.
183+
- Save the changes.
184+
185+
3. **Restart the Container (if necessary):**
186+
187+
The application automatically reloads the templates when it starts. If the container is already running, you may need to restart it to apply the changes.
188+
189+
#### Template Syntax and Variables
190+
191+
The templates use Go's `text/template` syntax and have access to the following variables:
192+
193+
- **For `title_prompt.tmpl`:**
194+
195+
- `{{.Language}}`: The language specified in `LLM_LANGUAGE` (default is `English`).
196+
- `{{.Content}}`: The content of the document.
197+
198+
- **For `tag_prompt.tmpl`:**
199+
200+
- `{{.Language}}`: The language specified in `LLM_LANGUAGE`.
201+
- `{{.AvailableTags}}`: A list (array) of available tags from paperless-ngx.
202+
- `{{.Title}}`: The suggested title for the document.
203+
- `{{.Content}}`: The content of the document.
204+
205+
**Example `title_prompt.tmpl`:**
206+
207+
```text
208+
I will provide you with the content of a document that has been partially read by OCR (so it may contain errors).
209+
Your task is to find a suitable document title that I can use as the title in the paperless-ngx program.
210+
Respond only with the title, without any additional information. The content is likely in {{.Language}}.
211+
212+
Be sure to add one fitting emoji at the beginning of the title to make it more visually appealing.
213+
214+
Content:
215+
{{.Content}}
216+
```
217+
218+
**Example `tag_prompt.tmpl`:**
219+
220+
```text
221+
I will provide you with the content and the title of a document. Your task is to select appropriate tags for the document from the list of available tags I will provide. Only select tags from the provided list. Respond only with the selected tags as a comma-separated list, without any additional information. The content is likely in {{.Language}}.
222+
223+
Available Tags:
224+
{{.AvailableTags | join ","}}
225+
226+
Title:
227+
{{.Title}}
228+
229+
Content:
230+
{{.Content}}
231+
232+
Please concisely select the {{.Language}} tags from the list above that best describe the document.
233+
Be very selective and only choose the most relevant tags since too many tags will make the document less discoverable.
234+
```
235+
236+
**Note:** Advanced users can utilize additional functions from the [Sprig](http://masterminds.github.io/sprig/) template library, as it is included in the application.
237+
123238
## Usage
124239

125240
1. **Tag Documents in paperless-ngx:**

go.mod

+9
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ go 1.22.0
55
toolchain go1.22.2
66

77
require (
8+
github.com/Masterminds/sprig/v3 v3.2.3
89
github.com/gin-gonic/gin v1.10.0
910
github.com/tmc/langchaingo v0.1.12
1011
)
1112

1213
require (
14+
github.com/Masterminds/goutils v1.1.1 // indirect
15+
github.com/Masterminds/semver/v3 v3.2.0 // indirect
1316
github.com/bytedance/sonic v1.11.6 // indirect
1417
github.com/bytedance/sonic/loader v0.1.1 // indirect
1518
github.com/cloudwego/base64x v0.1.4 // indirect
@@ -22,14 +25,20 @@ require (
2225
github.com/go-playground/validator/v10 v10.20.0 // indirect
2326
github.com/goccy/go-json v0.10.2 // indirect
2427
github.com/google/uuid v1.6.0 // indirect
28+
github.com/huandu/xstrings v1.3.3 // indirect
29+
github.com/imdario/mergo v0.3.13 // indirect
2530
github.com/json-iterator/go v1.1.12 // indirect
2631
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
2732
github.com/leodido/go-urn v1.4.0 // indirect
2833
github.com/mattn/go-isatty v0.0.20 // indirect
34+
github.com/mitchellh/copystructure v1.0.0 // indirect
35+
github.com/mitchellh/reflectwalk v1.0.0 // indirect
2936
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
3037
github.com/modern-go/reflect2 v1.0.2 // indirect
3138
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
3239
github.com/pkoukk/tiktoken-go v0.1.6 // indirect
40+
github.com/shopspring/decimal v1.2.0 // indirect
41+
github.com/spf13/cast v1.3.1 // indirect
3342
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
3443
github.com/ugorji/go/codec v1.2.12 // indirect
3544
golang.org/x/arch v0.8.0 // indirect

0 commit comments

Comments
 (0)