1{ config
2, lib
3, pkgs
4, ...
5}:
6let
7 inherit (lib) types;
8
9 format = pkgs.formats.yaml { };
10 cfg = config.services.private-gpt;
11in
12{
13 options = {
14 services.private-gpt = {
15 enable = lib.mkEnableOption "private-gpt for local large language models";
16 package = lib.mkPackageOption pkgs "private-gpt" { };
17
18 stateDir = lib.mkOption {
19 type = types.path;
20 default = "/var/lib/private-gpt";
21 description = "State directory of private-gpt.";
22 };
23
24 settings = lib.mkOption {
25 type = format.type;
26 default = {
27 llm = {
28 mode = "ollama";
29 tokenizer = "";
30 };
31 embedding = {
32 mode = "ollama";
33 };
34 ollama = {
35 llm_model = "llama3";
36 embedding_model = "nomic-embed-text";
37 api_base = "http://localhost:11434";
38 embedding_api_base = "http://localhost:11434";
39 keep_alive = "5m";
40 tfs_z = 1;
41 top_k = 40;
42 top_p = 0.9;
43 repeat_last_n = 64;
44 repeat_penalty = 1.2;
45 request_timeout = 120;
46 };
47 vectorstore = {
48 database = "qdrant";
49 };
50 qdrant = {
51 path = "/var/lib/private-gpt/vectorstore/qdrant";
52 };
53 data = {
54 local_data_folder = "/var/lib/private-gpt";
55 };
56 openai = { };
57 azopenai = { };
58 };
59 description = ''
60 settings-local.yaml for private-gpt
61 '';
62 };
63 };
64 };
65
66 config = lib.mkIf cfg.enable {
67 systemd.services.private-gpt = {
68 description = "Interact with your documents using the power of GPT, 100% privately, no data leaks";
69 wantedBy = [ "multi-user.target" ];
70 after = [ "network.target" ];
71
72 preStart =
73 let
74 config = format.generate "settings-local.yaml" (cfg.settings // { server.env_name = "local"; });
75 in
76 ''
77 mkdir -p ${cfg.stateDir}/{settings,huggingface,matplotlib,tiktoken_cache}
78 cp ${cfg.package.cl100k_base.tiktoken} ${cfg.stateDir}/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4
79 cp ${pkgs.python3Packages.private-gpt}/${pkgs.python3.sitePackages}/private_gpt/settings.yaml ${cfg.stateDir}/settings/settings.yaml
80 cp "${config}" "${cfg.stateDir}/settings/settings-local.yaml"
81 chmod 600 "${cfg.stateDir}/settings/settings-local.yaml"
82 '';
83
84 environment = {
85 PGPT_PROFILES = "local";
86 PGPT_SETTINGS_FOLDER = "${cfg.stateDir}/settings";
87 HF_HOME = "${cfg.stateDir}/huggingface";
88 TRANSFORMERS_OFFLINE = "1";
89 HF_DATASETS_OFFLINE = "1";
90 MPLCONFIGDIR = "${cfg.stateDir}/matplotlib";
91 };
92
93 serviceConfig = {
94 ExecStart = lib.getExe cfg.package;
95 WorkingDirectory = cfg.stateDir;
96 StateDirectory = "private-gpt";
97 RuntimeDirectory = "private-gpt";
98 RuntimeDirectoryMode = "0755";
99 PrivateTmp = true;
100 DynamicUser = true;
101 DevicePolicy = "closed";
102 LockPersonality = true;
103 MemoryDenyWriteExecute = true;
104 PrivateUsers = true;
105 ProtectHome = true;
106 ProtectHostname = true;
107 ProtectKernelLogs = true;
108 ProtectKernelModules = true;
109 ProtectKernelTunables = true;
110 ProtectControlGroups = true;
111 ProcSubset = "pid";
112 RestrictNamespaces = true;
113 RestrictRealtime = true;
114 SystemCallArchitectures = "native";
115 UMask = "0077";
116 };
117 };
118 };
119
120 meta.maintainers = with lib.maintainers; [ drupol ];
121}