@forwardimpact/svcllm 0.1.96 → 0.1.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forwardimpact/svcllm",
3
- "version": "0.1.96",
3
+ "version": "0.1.97",
4
4
  "description": "Language model service providing embeddings and completions for Guide",
5
5
  "license": "Apache-2.0",
6
6
  "author": "D. Olsson <hi@senzilla.io>",
@@ -23,5 +23,11 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "@forwardimpact/libharness": "^0.1.5"
26
+ },
27
+ "files": [
28
+ "proto/"
29
+ ],
30
+ "publishConfig": {
31
+ "access": "public"
26
32
  }
27
33
  }
@@ -0,0 +1,32 @@
1
+ syntax = "proto3";
2
+
3
+ package llm;
4
+
5
+ import "common.proto";
6
+ import "tool.proto";
7
+
8
+ service Llm {
9
+ rpc CreateEmbeddings(EmbeddingsRequest) returns (common.Embeddings);
10
+ rpc CreateCompletions(CompletionsRequest) returns (CompletionsResponse);
11
+ }
12
+
13
+ message EmbeddingsRequest {
14
+ repeated string input = 1;
15
+ string llm_token = 2;
16
+ optional string model = 3;
17
+ }
18
+
19
+ message CompletionsRequest {
20
+ string resource_id = 1;
21
+ string llm_token = 4;
22
+ optional string model = 5;
23
+ }
24
+
25
+ message CompletionsResponse {
26
+ string id = 1;
27
+ string object = 2;
28
+ int64 created = 3;
29
+ string model = 4;
30
+ repeated common.Choice choices = 5;
31
+ common.Usage usage = 6;
32
+ }
package/server.js DELETED
@@ -1,20 +0,0 @@
1
- import { Server, createClient } from "@forwardimpact/librpc";
2
- import { createServiceConfig } from "@forwardimpact/libconfig";
3
- import { createTracer } from "@forwardimpact/librpc";
4
- import { createLogger } from "@forwardimpact/libtelemetry";
5
-
6
- import { LlmService } from "./index.js";
7
-
8
- const config = await createServiceConfig("llm");
9
-
10
- // Initialize observability
11
- const logger = createLogger("llm");
12
- const tracer = await createTracer("llm");
13
-
14
- // Create memory client for fetching windows
15
- const memoryClient = await createClient("memory", logger, tracer);
16
-
17
- const service = new LlmService(config, memoryClient);
18
- const server = new Server(service, config, logger, tracer);
19
-
20
- await server.start();
package/test/llm.test.js DELETED
@@ -1,170 +0,0 @@
1
- import { test, describe, beforeEach } from "node:test";
2
- import assert from "node:assert";
3
-
4
- // Module under test
5
- import { LlmService } from "../index.js";
6
- import {
7
- createMockConfig,
8
- createMockMemoryClient,
9
- } from "@forwardimpact/libharness";
10
-
11
- describe("llm service", () => {
12
- describe("LlmService", () => {
13
- test("exports LlmService class", () => {
14
- assert.strictEqual(typeof LlmService, "function");
15
- assert.ok(LlmService.prototype);
16
- });
17
-
18
- test("LlmService has CreateCompletions method", () => {
19
- assert.strictEqual(
20
- typeof LlmService.prototype.CreateCompletions,
21
- "function",
22
- );
23
- });
24
-
25
- test("LlmService has CreateEmbeddings method", () => {
26
- assert.strictEqual(
27
- typeof LlmService.prototype.CreateEmbeddings,
28
- "function",
29
- );
30
- });
31
-
32
- test("LlmService has proper method signatures", () => {
33
- const methods = Object.getOwnPropertyNames(LlmService.prototype);
34
- assert(methods.includes("CreateCompletions"));
35
- assert(methods.includes("CreateEmbeddings"));
36
- assert(methods.includes("constructor"));
37
- });
38
- });
39
-
40
- describe("LlmService business logic", () => {
41
- let mockConfig;
42
- let mockMemoryClient;
43
- let mockLlmFactory;
44
- let mockCopilot;
45
-
46
- beforeEach(() => {
47
- mockConfig = createMockConfig("llm", {
48
- model: "gpt-4o",
49
- llmBaseUrl: () => "https://test.api.com",
50
- embeddingBaseUrl: () => "http://localhost:8090",
51
- });
52
-
53
- mockMemoryClient = createMockMemoryClient();
54
-
55
- mockCopilot = {
56
- createCompletions: async () => ({
57
- id: "test-completion",
58
- choices: [
59
- { message: { role: "assistant", content: "Test response" } },
60
- ],
61
- usage: { total_tokens: 100 },
62
- }),
63
- createEmbeddings: async () => ({
64
- data: [{ index: 0, embedding: [0.1, 0.2, 0.3] }],
65
- }),
66
- };
67
-
68
- mockLlmFactory = (
69
- token,
70
- model,
71
- _baseUrl,
72
- _embeddingBaseUrl,
73
- _temperature,
74
- ) => {
75
- assert.strictEqual(model, mockConfig.model);
76
- return mockCopilot;
77
- };
78
- });
79
-
80
- test("constructor stores llmFactory and memoryClient", () => {
81
- const service = new LlmService(
82
- mockConfig,
83
- mockMemoryClient,
84
- mockLlmFactory,
85
- );
86
-
87
- // Test that constructor succeeds - actual validation happens at usage time
88
- assert.ok(service);
89
- assert.strictEqual(service.config, mockConfig);
90
- });
91
-
92
- test("creates service instance with valid parameters", () => {
93
- const service = new LlmService(
94
- mockConfig,
95
- mockMemoryClient,
96
- mockLlmFactory,
97
- );
98
-
99
- assert.ok(service);
100
- assert.strictEqual(service.config, mockConfig);
101
- });
102
-
103
- test("CreateCompletions requires resource_id", async () => {
104
- const service = new LlmService(
105
- mockConfig,
106
- mockMemoryClient,
107
- mockLlmFactory,
108
- );
109
-
110
- await assert.rejects(
111
- async () => {
112
- await service.CreateCompletions({
113
- llm_token: "test-token",
114
- messages: [{ role: "user", content: "Hello" }],
115
- tools: [],
116
- });
117
- },
118
- { message: "resource_id is required for CreateCompletions" },
119
- );
120
- });
121
-
122
- test("CreateCompletions fetches memory window when resource_id provided", async () => {
123
- let memoryWindowCalled = false;
124
- const mockMemoryClientWithTracking = {
125
- GetWindow: async (req) => {
126
- memoryWindowCalled = true;
127
- assert.ok(req.resource_id);
128
- assert.ok(req.model);
129
- return {
130
- messages: [{ role: "system", content: "You are an assistant" }],
131
- tools: [],
132
- temperature: "0.7",
133
- };
134
- },
135
- };
136
-
137
- const service = new LlmService(
138
- mockConfig,
139
- mockMemoryClientWithTracking,
140
- mockLlmFactory,
141
- );
142
-
143
- const result = await service.CreateCompletions({
144
- llm_token: "test-token",
145
- resource_id: "test-conversation-id",
146
- });
147
-
148
- assert.ok(result);
149
- assert.ok(memoryWindowCalled, "Memory window should be fetched");
150
- });
151
-
152
- test("CreateEmbeddings processes chunks correctly", async () => {
153
- const service = new LlmService(
154
- mockConfig,
155
- mockMemoryClient,
156
- mockLlmFactory,
157
- );
158
-
159
- const result = await service.CreateEmbeddings({
160
- llm_token: "test-token",
161
- input: ["test chunk"],
162
- });
163
-
164
- assert.ok(result);
165
- assert.ok(result.data);
166
- assert.strictEqual(result.data.length, 1);
167
- assert.deepStrictEqual(result.data[0].embedding, [0.1, 0.2, 0.3]);
168
- });
169
- });
170
- });