@sweetoburrito/backstage-plugin-ai-assistant-backend 0.2.1 → 0.4.0
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/dist/database/chat-store.cjs.js +7 -1
- package/dist/database/chat-store.cjs.js.map +1 -1
- package/dist/plugin.cjs.js +3 -1
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/services/chat.cjs.js +50 -14
- package/dist/services/chat.cjs.js.map +1 -1
- package/dist/services/prompt.cjs.js.map +1 -1
- package/dist/services/router/chat.cjs.js +3 -6
- package/dist/services/router/chat.cjs.js.map +1 -1
- package/dist/services/router/models.cjs.js +0 -3
- package/dist/services/router/models.cjs.js.map +1 -1
- package/package.json +13 -1
|
@@ -17,7 +17,7 @@ class ChatStore {
|
|
|
17
17
|
return this.client(TABLE_NAME);
|
|
18
18
|
}
|
|
19
19
|
async getChatMessages(conversationId, userRef, limit) {
|
|
20
|
-
let query = this.table().where({ conversation_id: conversationId, userRef }).select("*");
|
|
20
|
+
let query = this.table().where({ conversation_id: conversationId, userRef }).select("*").orderBy("created_at", "asc");
|
|
21
21
|
if (typeof limit === "number") {
|
|
22
22
|
query = query.limit(limit).orderBy("created_at", "desc");
|
|
23
23
|
}
|
|
@@ -40,6 +40,12 @@ class ChatStore {
|
|
|
40
40
|
}));
|
|
41
41
|
await this.table().insert(rows);
|
|
42
42
|
}
|
|
43
|
+
async updateMessage(message) {
|
|
44
|
+
await this.table().where({ id: message.id }).update({
|
|
45
|
+
role: message.role,
|
|
46
|
+
content: message.content
|
|
47
|
+
});
|
|
48
|
+
}
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
exports.ChatStore = ChatStore;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-store.cjs.js","sources":["../../src/database/chat-store.ts"],"sourcesContent":["import { DatabaseService } from '@backstage/backend-plugin-api';\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-
|
|
1
|
+
{"version":3,"file":"chat-store.cjs.js","sources":["../../src/database/chat-store.ts"],"sourcesContent":["import { DatabaseService } from '@backstage/backend-plugin-api';\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\n\nimport { Knex } from 'knex';\n\nconst TABLE_NAME = 'conversation';\n\nexport type ChatStoreOptions = {\n database: DatabaseService;\n};\n\nexport class ChatStore {\n /**\n * Creates an instance of ChatStore.\n * @param client - The Knex client to interact with the PostgreSQL database.\n */\n constructor(private readonly client: Knex) {}\n\n static async fromConfig({ database }: ChatStoreOptions) {\n const client = await database.getClient();\n return new ChatStore(client);\n }\n\n table() {\n return this.client(TABLE_NAME);\n }\n\n async getChatMessages(\n conversationId: string,\n userRef: string,\n limit?: number,\n ): Promise<Required<Message>[]> {\n let query = this.table()\n .where({ conversation_id: conversationId, userRef })\n .select('*')\n .orderBy('created_at', 'asc');\n\n if (typeof limit === 'number') {\n query = query.limit(limit).orderBy('created_at', 'desc');\n }\n\n const rows = await query;\n\n const chatMessages: Required<Message>[] = rows.map(row => ({\n role: row.role,\n content: row.content,\n id: row.id,\n }));\n\n return chatMessages;\n }\n\n async addChatMessage(\n messages: Message[],\n userRef: string,\n conversationId: string,\n ): Promise<void> {\n const rows = messages.map(msg => ({\n id: msg.id,\n conversation_id: conversationId,\n role: msg.role,\n content: msg.content,\n userRef,\n created_at: this.client.fn.now(),\n }));\n\n await this.table().insert(rows);\n }\n\n async updateMessage(message: Required<Message>) {\n await this.table().where({ id: message.id }).update({\n role: message.role,\n content: message.content,\n });\n }\n}\n"],"names":[],"mappings":";;AAKA,MAAM,UAAA,GAAa,cAAA;AAMZ,MAAM,SAAA,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAKrB,YAA6B,MAAA,EAAc;AAAd,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAe;AAAA,EAE5C,aAAa,UAAA,CAAW,EAAE,QAAA,EAAS,EAAqB;AACtD,IAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,SAAA,EAAU;AACxC,IAAA,OAAO,IAAI,UAAU,MAAM,CAAA;AAAA,EAC7B;AAAA,EAEA,KAAA,GAAQ;AACN,IAAA,OAAO,IAAA,CAAK,OAAO,UAAU,CAAA;AAAA,EAC/B;AAAA,EAEA,MAAM,eAAA,CACJ,cAAA,EACA,OAAA,EACA,KAAA,EAC8B;AAC9B,IAAA,IAAI,QAAQ,IAAA,CAAK,KAAA,EAAM,CACpB,KAAA,CAAM,EAAE,eAAA,EAAiB,cAAA,EAAgB,OAAA,EAAS,EAClD,MAAA,CAAO,GAAG,CAAA,CACV,OAAA,CAAQ,cAAc,KAAK,CAAA;AAE9B,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,KAAA,GAAQ,MAAM,KAAA,CAAM,KAAK,CAAA,CAAE,OAAA,CAAQ,cAAc,MAAM,CAAA;AAAA,IACzD;AAEA,IAAA,MAAM,OAAO,MAAM,KAAA;AAEnB,IAAA,MAAM,YAAA,GAAoC,IAAA,CAAK,GAAA,CAAI,CAAA,GAAA,MAAQ;AAAA,MACzD,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,IAAI,GAAA,CAAI;AAAA,KACV,CAAE,CAAA;AAEF,IAAA,OAAO,YAAA;AAAA,EACT;AAAA,EAEA,MAAM,cAAA,CACJ,QAAA,EACA,OAAA,EACA,cAAA,EACe;AACf,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,GAAA,CAAI,CAAA,GAAA,MAAQ;AAAA,MAChC,IAAI,GAAA,CAAI,EAAA;AAAA,MACR,eAAA,EAAiB,cAAA;AAAA,MACjB,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,OAAA;AAAA,MACA,UAAA,EAAY,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,GAAA;AAAI,KACjC,CAAE,CAAA;AAEF,IAAA,MAAM,IAAA,CAAK,KAAA,EAAM,CAAE,MAAA,CAAO,IAAI,CAAA;AAAA,EAChC;AAAA,EAEA,MAAM,cAAc,OAAA,EAA4B;AAC9C,IAAA,MAAM,IAAA,CAAK,KAAA,EAAM,CAAE,KAAA,CAAM,EAAE,IAAI,OAAA,CAAQ,EAAA,EAAI,CAAA,CAAE,MAAA,CAAO;AAAA,MAClD,MAAM,OAAA,CAAQ,IAAA;AAAA,MACd,SAAS,OAAA,CAAQ;AAAA,KAClB,CAAA;AAAA,EACH;AACF;;;;"}
|
package/dist/plugin.cjs.js
CHANGED
|
@@ -8,6 +8,7 @@ var chat = require('./services/chat.cjs.js');
|
|
|
8
8
|
var prompt = require('./services/prompt.cjs.js');
|
|
9
9
|
var migrations = require('./database/migrations.cjs.js');
|
|
10
10
|
var pgVectorStore = require('./database/pg-vector-store.cjs.js');
|
|
11
|
+
var pluginSignalsNode = require('@backstage/plugin-signals-node');
|
|
11
12
|
|
|
12
13
|
const aiAssistantPlugin = backendPluginApi.createBackendPlugin({
|
|
13
14
|
pluginId: "ai-assistant",
|
|
@@ -48,7 +49,8 @@ const aiAssistantPlugin = backendPluginApi.createBackendPlugin({
|
|
|
48
49
|
config: backendPluginApi.coreServices.rootConfig,
|
|
49
50
|
scheduler: backendPluginApi.coreServices.scheduler,
|
|
50
51
|
httpAuth: backendPluginApi.coreServices.httpAuth,
|
|
51
|
-
userInfo: backendPluginApi.coreServices.userInfo
|
|
52
|
+
userInfo: backendPluginApi.coreServices.userInfo,
|
|
53
|
+
signals: pluginSignalsNode.signalsServiceRef
|
|
52
54
|
},
|
|
53
55
|
async init(options) {
|
|
54
56
|
const { httpRouter, database } = options;
|
package/dist/plugin.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './services/router';\nimport {\n dataIngestorExtensionPoint,\n EmbeddingsProvider,\n embeddingsProviderExtensionPoint,\n Ingestor,\n Model,\n modelProviderExtensionPoint,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport { createDataIngestionPipeline } from './services/ingestor';\nimport { createChatService } from './services/chat';\nimport { createPromptBuilder } from './services/prompt';\nimport { applyDatabaseMigrations } from './database/migrations';\nimport { PgVectorStore } from './database';\n\n/**\n * aiAssistantPlugin backend plugin\n *\n * @public\n */\nexport const aiAssistantPlugin = createBackendPlugin({\n pluginId: 'ai-assistant',\n register(env) {\n const ingestors: Ingestor[] = [];\n const models: Model[] = [];\n\n let embeddingsProvider: EmbeddingsProvider;\n\n env.registerExtensionPoint(dataIngestorExtensionPoint, {\n registerIngestor: ingestor => {\n const existingIngestor = ingestors.find(i => i.id === ingestor.id);\n if (existingIngestor) {\n throw new Error(\n `Ingestor with id ${ingestor.id} is already registered.`,\n );\n }\n ingestors.push(ingestor);\n },\n });\n\n env.registerExtensionPoint(embeddingsProviderExtensionPoint, {\n register: provider => {\n embeddingsProvider = provider;\n },\n });\n\n env.registerExtensionPoint(modelProviderExtensionPoint, {\n register: model => {\n const existingModel = models.find(m => m.id === model.id);\n if (existingModel) {\n throw new Error(`Model with id ${model.id} is already registered.`);\n }\n models.push(model);\n },\n });\n\n env.registerInit({\n deps: {\n httpRouter: coreServices.httpRouter,\n database: coreServices.database,\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n scheduler: coreServices.scheduler,\n httpAuth: coreServices.httpAuth,\n userInfo: coreServices.userInfo,\n },\n\n async init(options) {\n const { httpRouter, database } = options;\n const client = await database.getClient();\n\n await applyDatabaseMigrations(client);\n\n const vectorStore = await PgVectorStore.fromConfig(options);\n\n if (!embeddingsProvider) {\n throw new Error('No Embeddings Provider was registered.');\n }\n\n vectorStore.connectEmbeddings(await embeddingsProvider.getEmbeddings());\n\n const dataIngestionPipeline = createDataIngestionPipeline({\n ...options,\n vectorStore,\n ingestors,\n });\n\n const promptBuilder = createPromptBuilder(options);\n\n const chat = await createChatService({\n ...options,\n models,\n vectorStore,\n promptBuilder,\n });\n\n httpRouter.use(await createRouter({ ...options, chat }));\n dataIngestionPipeline.start();\n },\n });\n },\n});\n"],"names":["createBackendPlugin","dataIngestorExtensionPoint","embeddingsProviderExtensionPoint","modelProviderExtensionPoint","coreServices","applyDatabaseMigrations","PgVectorStore","createDataIngestionPipeline","createPromptBuilder","chat","createChatService","createRouter"],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './services/router';\nimport {\n dataIngestorExtensionPoint,\n EmbeddingsProvider,\n embeddingsProviderExtensionPoint,\n Ingestor,\n Model,\n modelProviderExtensionPoint,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport { createDataIngestionPipeline } from './services/ingestor';\nimport { createChatService } from './services/chat';\nimport { createPromptBuilder } from './services/prompt';\nimport { applyDatabaseMigrations } from './database/migrations';\nimport { PgVectorStore } from './database';\nimport { signalsServiceRef } from '@backstage/plugin-signals-node';\n\n/**\n * aiAssistantPlugin backend plugin\n *\n * @public\n */\nexport const aiAssistantPlugin = createBackendPlugin({\n pluginId: 'ai-assistant',\n register(env) {\n const ingestors: Ingestor[] = [];\n const models: Model[] = [];\n\n let embeddingsProvider: EmbeddingsProvider;\n\n env.registerExtensionPoint(dataIngestorExtensionPoint, {\n registerIngestor: ingestor => {\n const existingIngestor = ingestors.find(i => i.id === ingestor.id);\n if (existingIngestor) {\n throw new Error(\n `Ingestor with id ${ingestor.id} is already registered.`,\n );\n }\n ingestors.push(ingestor);\n },\n });\n\n env.registerExtensionPoint(embeddingsProviderExtensionPoint, {\n register: provider => {\n embeddingsProvider = provider;\n },\n });\n\n env.registerExtensionPoint(modelProviderExtensionPoint, {\n register: model => {\n const existingModel = models.find(m => m.id === model.id);\n if (existingModel) {\n throw new Error(`Model with id ${model.id} is already registered.`);\n }\n models.push(model);\n },\n });\n\n env.registerInit({\n deps: {\n httpRouter: coreServices.httpRouter,\n database: coreServices.database,\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n scheduler: coreServices.scheduler,\n httpAuth: coreServices.httpAuth,\n userInfo: coreServices.userInfo,\n signals: signalsServiceRef,\n },\n\n async init(options) {\n const { httpRouter, database } = options;\n const client = await database.getClient();\n\n await applyDatabaseMigrations(client);\n\n const vectorStore = await PgVectorStore.fromConfig(options);\n\n if (!embeddingsProvider) {\n throw new Error('No Embeddings Provider was registered.');\n }\n\n vectorStore.connectEmbeddings(await embeddingsProvider.getEmbeddings());\n\n const dataIngestionPipeline = createDataIngestionPipeline({\n ...options,\n vectorStore,\n ingestors,\n });\n\n const promptBuilder = createPromptBuilder(options);\n\n const chat = await createChatService({\n ...options,\n models,\n vectorStore,\n promptBuilder,\n });\n\n httpRouter.use(await createRouter({ ...options, chat }));\n dataIngestionPipeline.start();\n },\n });\n },\n});\n"],"names":["createBackendPlugin","dataIngestorExtensionPoint","embeddingsProviderExtensionPoint","modelProviderExtensionPoint","coreServices","signalsServiceRef","applyDatabaseMigrations","PgVectorStore","createDataIngestionPipeline","createPromptBuilder","chat","createChatService","createRouter"],"mappings":"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"}
|
|
@@ -8,18 +8,48 @@ const createChatService = async ({
|
|
|
8
8
|
logger,
|
|
9
9
|
vectorStore,
|
|
10
10
|
promptBuilder,
|
|
11
|
-
database
|
|
11
|
+
database,
|
|
12
|
+
signals
|
|
12
13
|
}) => {
|
|
13
14
|
logger.info(`Available models: ${models.map((m) => m.id).join(", ")}`);
|
|
14
15
|
const chatStore$1 = await chatStore.ChatStore.fromConfig({ database });
|
|
15
16
|
const getChatModelById = (id) => {
|
|
16
17
|
return models.find((model) => model.id === id)?.chatModel;
|
|
17
18
|
};
|
|
19
|
+
const streamMessage = async ({
|
|
20
|
+
modelId,
|
|
21
|
+
messages,
|
|
22
|
+
messageId,
|
|
23
|
+
userEntityRef
|
|
24
|
+
}) => {
|
|
25
|
+
const model = getChatModelById(modelId);
|
|
26
|
+
if (!model) {
|
|
27
|
+
throw new Error(`Model with id ${modelId} not found`);
|
|
28
|
+
}
|
|
29
|
+
const promptStream = await model.stream(messages);
|
|
30
|
+
const aiMessage = {
|
|
31
|
+
id: messageId,
|
|
32
|
+
role: "assistant",
|
|
33
|
+
content: ""
|
|
34
|
+
};
|
|
35
|
+
for await (const chunk of promptStream) {
|
|
36
|
+
aiMessage.content += chunk.content ?? "";
|
|
37
|
+
chatStore$1.updateMessage(aiMessage);
|
|
38
|
+
signals.publish({
|
|
39
|
+
channel: `ai-assistant.chat.message-stream:${messageId}`,
|
|
40
|
+
message: aiMessage,
|
|
41
|
+
recipients: {
|
|
42
|
+
type: "user",
|
|
43
|
+
entityRef: userEntityRef
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
};
|
|
18
48
|
const prompt = async ({
|
|
19
49
|
conversationId,
|
|
20
50
|
messages,
|
|
21
51
|
modelId,
|
|
22
|
-
stream,
|
|
52
|
+
stream = true,
|
|
23
53
|
userEntityRef
|
|
24
54
|
}) => {
|
|
25
55
|
const model = getChatModelById(modelId);
|
|
@@ -39,20 +69,26 @@ const createChatService = async ({
|
|
|
39
69
|
[...recentConversationMessages, ...messages],
|
|
40
70
|
context
|
|
41
71
|
);
|
|
42
|
-
const
|
|
72
|
+
const messageId = uuid.v4();
|
|
73
|
+
const aiMessage = {
|
|
74
|
+
id: messageId,
|
|
75
|
+
role: "assistant",
|
|
76
|
+
content: ""
|
|
77
|
+
};
|
|
78
|
+
await chatStore$1.addChatMessage([aiMessage], userEntityRef, conversationId);
|
|
43
79
|
if (stream) {
|
|
44
|
-
|
|
80
|
+
streamMessage({
|
|
81
|
+
modelId,
|
|
82
|
+
messages: promptMessages,
|
|
83
|
+
messageId,
|
|
84
|
+
userEntityRef
|
|
85
|
+
});
|
|
86
|
+
return [aiMessage];
|
|
45
87
|
}
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
role: "assistant",
|
|
51
|
-
content: response.text
|
|
52
|
-
}
|
|
53
|
-
];
|
|
54
|
-
chatStore$1.addChatMessage(aiMessages, userEntityRef, conversationId);
|
|
55
|
-
return aiMessages;
|
|
88
|
+
const { text } = await model.invoke(promptMessages);
|
|
89
|
+
aiMessage.content = text;
|
|
90
|
+
await chatStore$1.updateMessage(aiMessage);
|
|
91
|
+
return [aiMessage];
|
|
56
92
|
};
|
|
57
93
|
const getAvailableModels = async () => {
|
|
58
94
|
return models.map((x) => x.id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.cjs.js","sources":["../../src/services/chat.ts"],"sourcesContent":["import {\n
|
|
1
|
+
{"version":3,"file":"chat.cjs.js","sources":["../../src/services/chat.ts"],"sourcesContent":["import {\n Model,\n VectorStore,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport {\n LoggerService,\n RootConfigService,\n DatabaseService,\n} from '@backstage/backend-plugin-api';\nimport { PromptBuilder } from './prompt';\nimport { v4 as uuid } from 'uuid';\nimport { ChatStore } from '../database/chat-store';\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\nimport { SignalsService } from '@backstage/plugin-signals-node';\n\nexport type ChatServiceOptions = {\n models: Model[];\n logger: LoggerService;\n vectorStore: VectorStore;\n config: RootConfigService;\n promptBuilder: PromptBuilder;\n database: DatabaseService;\n signals: SignalsService;\n};\n\ntype StreamOptions = {\n modelId: string;\n messages: Message[];\n messageId: string;\n userEntityRef: string;\n};\n\ntype PromptOptions = {\n modelId: string;\n messages: Message[];\n conversationId: string;\n stream?: boolean;\n userEntityRef: string;\n};\n\ntype GetConversationOptions = {\n conversationId: string;\n userEntityRef: string;\n};\n\nexport type ChatService = {\n prompt: (options: PromptOptions) => Promise<Required<Message>[]>;\n getAvailableModels: () => Promise<string[]>;\n getConversation: (\n options: GetConversationOptions,\n ) => Promise<Required<Message>[]>;\n};\n\nexport const createChatService = async ({\n models,\n logger,\n vectorStore,\n promptBuilder,\n database,\n signals,\n}: ChatServiceOptions): Promise<ChatService> => {\n logger.info(`Available models: ${models.map(m => m.id).join(', ')}`);\n\n const chatStore = await ChatStore.fromConfig({ database });\n\n const getChatModelById = (id: string) => {\n return models.find(model => model.id === id)?.chatModel;\n };\n\n const streamMessage = async ({\n modelId,\n messages,\n messageId,\n userEntityRef,\n }: StreamOptions) => {\n const model = getChatModelById(modelId);\n\n if (!model) {\n throw new Error(`Model with id ${modelId} not found`);\n }\n\n const promptStream = await model.stream(messages);\n\n const aiMessage: Required<Message> = {\n id: messageId,\n role: 'assistant',\n content: '',\n };\n\n for await (const chunk of promptStream) {\n aiMessage.content += chunk.content ?? '';\n\n chatStore.updateMessage(aiMessage);\n\n signals.publish({\n channel: `ai-assistant.chat.message-stream:${messageId}`,\n message: aiMessage,\n recipients: {\n type: 'user',\n entityRef: userEntityRef,\n },\n });\n }\n };\n\n const prompt: ChatService['prompt'] = async ({\n conversationId,\n messages,\n modelId,\n stream = true,\n userEntityRef,\n }: PromptOptions) => {\n const model = getChatModelById(modelId);\n\n if (!model) {\n throw new Error(`Model with id ${modelId} not found`);\n }\n\n chatStore.addChatMessage(messages, userEntityRef, conversationId);\n\n const context = await vectorStore.similaritySearch(\n messages\n .filter(m => m.role === 'user')\n .map(m => m.content)\n .join('\\n'),\n );\n\n const recentConversationMessages = await chatStore.getChatMessages(\n conversationId,\n userEntityRef,\n 10,\n );\n\n const promptMessages = promptBuilder.buildPrompt(\n [...recentConversationMessages, ...messages],\n context,\n );\n\n const messageId: string = uuid();\n\n const aiMessage: Required<Message> = {\n id: messageId,\n role: 'assistant',\n content: '',\n };\n\n await chatStore.addChatMessage([aiMessage], userEntityRef, conversationId);\n\n if (stream) {\n streamMessage({\n modelId,\n messages: promptMessages,\n messageId,\n userEntityRef,\n });\n\n return [aiMessage];\n }\n const { text } = await model.invoke(promptMessages);\n\n aiMessage.content = text;\n\n await chatStore.updateMessage(aiMessage);\n\n return [aiMessage];\n };\n\n const getAvailableModels: ChatService['getAvailableModels'] = async () => {\n return models.map(x => x.id);\n };\n\n const getConversation: ChatService['getConversation'] = async (\n options: GetConversationOptions,\n ) => {\n const { conversationId, userEntityRef } = options;\n\n const conversation = await chatStore.getChatMessages(\n conversationId,\n userEntityRef,\n );\n\n return conversation;\n };\n\n return {\n prompt,\n getAvailableModels,\n getConversation,\n };\n};\n"],"names":["chatStore","ChatStore","uuid"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.cjs.js","sources":["../../src/services/prompt.ts"],"sourcesContent":["import { RootConfigService } from '@backstage/backend-plugin-api';\nimport {
|
|
1
|
+
{"version":3,"file":"prompt.cjs.js","sources":["../../src/services/prompt.ts"],"sourcesContent":["import { RootConfigService } from '@backstage/backend-plugin-api';\nimport { EmbeddingDocument } from '@sweetoburrito/backstage-plugin-ai-assistant-node';\n\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\n\ntype PromptBuilderOptions = {\n config: RootConfigService;\n};\n\nexport type PromptBuilder = {\n buildPrompt: (\n chatHistory: Message[],\n promptContext: EmbeddingDocument[],\n ) => Message[];\n};\n\nconst DEFAULT_SYSTEM_PROMPT = `\nYou are a helpful assistant that answers questions based on provided context from various documents. The context may come from sources such as internal wikis, code repositories, technical documentation, or other structured or unstructured data.\n\nRules:\n1. Always base your answers on the provided context. Do not make up information.\n2. When relevant, cite or reference the source information provided in the context.\n3. Format answers clearly and concisely. Use bullet points for lists when appropriate.\n4. Maintain a professional, friendly, and helpful tone.\n5. Return only the relevant information without any filler or unnecessary details.\n6. If you don't know the answer, admit it and suggest ways to find the information.\n7. Always return a well-structured response using markdown.\n`;\n\nexport const createPromptBuilder = ({\n config,\n}: PromptBuilderOptions): PromptBuilder => {\n const system = config.getOptionalString('system') || DEFAULT_SYSTEM_PROMPT;\n\n const getContext = (context: EmbeddingDocument[]) => {\n return `\n Context:\n ${context.map(doc => JSON.stringify(doc)).join('\\n')}\n `;\n };\n\n const buildPrompt: PromptBuilder['buildPrompt'] = (\n chatHistory,\n promptContext,\n ) => {\n const context = getContext(promptContext);\n\n return [\n {\n role: 'system',\n content: system.concat(context),\n },\n ...chatHistory,\n ];\n };\n\n return {\n buildPrompt,\n };\n};\n"],"names":[],"mappings":";;AAgBA,MAAM,qBAAA,GAAwB;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAavB,MAAM,sBAAsB,CAAC;AAAA,EAClC;AACF,CAAA,KAA2C;AACzC,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,iBAAA,CAAkB,QAAQ,CAAA,IAAK,qBAAA;AAErD,EAAA,MAAM,UAAA,GAAa,CAAC,OAAA,KAAiC;AACnD,IAAA,OAAO;AAAA;AAAA,IAAA,EAEL,OAAA,CAAQ,GAAA,CAAI,CAAA,GAAA,KAAO,IAAA,CAAK,SAAA,CAAU,GAAG,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC;AAAA,IAAA,CAAA;AAAA,EAEtD,CAAA;AAEA,EAAA,MAAM,WAAA,GAA4C,CAChD,WAAA,EACA,aAAA,KACG;AACH,IAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AAExC,IAAA,OAAO;AAAA,MACL;AAAA,QACE,IAAA,EAAM,QAAA;AAAA,QACN,OAAA,EAAS,MAAA,CAAO,MAAA,CAAO,OAAO;AAAA,OAChC;AAAA,MACA,GAAG;AAAA,KACL;AAAA,EACF,CAAA;AAEA,EAAA,OAAO;AAAA,IACL;AAAA,GACF;AACF;;;;"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var express = require('express');
|
|
4
3
|
var Router = require('express-promise-router');
|
|
5
4
|
var z = require('zod');
|
|
6
5
|
var validation = require('./middleware/validation.cjs.js');
|
|
@@ -8,14 +7,12 @@ var uuid = require('uuid');
|
|
|
8
7
|
|
|
9
8
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
10
9
|
|
|
11
|
-
var express__default = /*#__PURE__*/_interopDefaultCompat(express);
|
|
12
10
|
var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
|
|
13
11
|
var z__default = /*#__PURE__*/_interopDefaultCompat(z);
|
|
14
12
|
|
|
15
13
|
async function createChatRouter(options) {
|
|
16
14
|
const { chat, httpAuth, userInfo } = options;
|
|
17
15
|
const router = Router__default.default();
|
|
18
|
-
router.use(express__default.default.json());
|
|
19
16
|
const messageSchema = z__default.default.object({
|
|
20
17
|
messages: z__default.default.array(
|
|
21
18
|
z__default.default.object({
|
|
@@ -26,7 +23,7 @@ async function createChatRouter(options) {
|
|
|
26
23
|
),
|
|
27
24
|
modelId: z__default.default.string(),
|
|
28
25
|
conversationId: z__default.default.string().uuid().optional().default(uuid.v4),
|
|
29
|
-
stream: z__default.default.boolean().optional()
|
|
26
|
+
stream: z__default.default.boolean().optional()
|
|
30
27
|
});
|
|
31
28
|
router.post(
|
|
32
29
|
"/message",
|
|
@@ -51,8 +48,8 @@ async function createChatRouter(options) {
|
|
|
51
48
|
const chatSchema = z__default.default.object({
|
|
52
49
|
id: z__default.default.string().uuid()
|
|
53
50
|
});
|
|
54
|
-
router.get("
|
|
55
|
-
const { id } = req.
|
|
51
|
+
router.get("/:id", validation.validation(chatSchema, "params"), async (req, res) => {
|
|
52
|
+
const { id } = req.params;
|
|
56
53
|
const credentials = await httpAuth.credentials(req);
|
|
57
54
|
const { userEntityRef } = await userInfo.getUserInfo(credentials);
|
|
58
55
|
const conversation = await chat.getConversation({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.cjs.js","sources":["../../../src/services/router/chat.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport { ChatService } from '../chat';\nimport z from 'zod';\nimport { validation } from './middleware/validation';\nimport { v4 as uuid } from 'uuid';\nimport {\n DatabaseService,\n HttpAuthService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\n\nexport type ChatRouterOptions = {\n chat: ChatService;\n database: DatabaseService;\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n};\n\nexport async function createChatRouter(\n options: ChatRouterOptions,\n): Promise<express.Router> {\n const { chat, httpAuth, userInfo } = options;\n\n const router = Router();\n
|
|
1
|
+
{"version":3,"file":"chat.cjs.js","sources":["../../../src/services/router/chat.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport { ChatService } from '../chat';\nimport z from 'zod';\nimport { validation } from './middleware/validation';\nimport { v4 as uuid } from 'uuid';\nimport {\n DatabaseService,\n HttpAuthService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\n\nexport type ChatRouterOptions = {\n chat: ChatService;\n database: DatabaseService;\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n};\n\nexport async function createChatRouter(\n options: ChatRouterOptions,\n): Promise<express.Router> {\n const { chat, httpAuth, userInfo } = options;\n\n const router = Router();\n\n const messageSchema = z.object({\n messages: z.array(\n z.object({\n id: z.string().uuid().optional().default(uuid),\n role: z.string(),\n content: z.string(),\n }),\n ),\n modelId: z.string(),\n conversationId: z.string().uuid().optional().default(uuid),\n stream: z.boolean().optional(),\n });\n\n router.post(\n '/message',\n validation(messageSchema, 'body'),\n async (req, res) => {\n const { messages, conversationId, modelId, stream } = req.body;\n\n const credentials = await httpAuth.credentials(req);\n const { userEntityRef } = await userInfo.getUserInfo(credentials);\n\n const responseMessages = await chat.prompt({\n modelId,\n messages,\n conversationId,\n stream,\n userEntityRef,\n });\n\n res.json({\n messages: responseMessages,\n conversationId,\n });\n },\n );\n\n const chatSchema = z.object({\n id: z.string().uuid(),\n });\n\n router.get('/:id', validation(chatSchema, 'params'), async (req, res) => {\n const { id } = req.params;\n\n const credentials = await httpAuth.credentials(req);\n const { userEntityRef } = await userInfo.getUserInfo(credentials);\n\n const conversation = await chat.getConversation({\n conversationId: id,\n userEntityRef,\n });\n\n res.json({ conversation });\n });\n\n return router;\n}\n"],"names":["Router","z","uuid","validation"],"mappings":";;;;;;;;;;;;AAmBA,eAAsB,iBACpB,OAAA,EACyB;AACzB,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAU,QAAA,EAAS,GAAI,OAAA;AAErC,EAAA,MAAM,SAASA,uBAAA,EAAO;AAEtB,EAAA,MAAM,aAAA,GAAgBC,mBAAE,MAAA,CAAO;AAAA,IAC7B,UAAUA,kBAAA,CAAE,KAAA;AAAA,MACVA,mBAAE,MAAA,CAAO;AAAA,QACP,EAAA,EAAIA,mBAAE,MAAA,EAAO,CAAE,MAAK,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQC,OAAI,CAAA;AAAA,QAC7C,IAAA,EAAMD,mBAAE,MAAA,EAAO;AAAA,QACf,OAAA,EAASA,mBAAE,MAAA;AAAO,OACnB;AAAA,KACH;AAAA,IACA,OAAA,EAASA,mBAAE,MAAA,EAAO;AAAA,IAClB,cAAA,EAAgBA,mBAAE,MAAA,EAAO,CAAE,MAAK,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQC,OAAI,CAAA;AAAA,IACzD,MAAA,EAAQD,kBAAA,CAAE,OAAA,EAAQ,CAAE,QAAA;AAAS,GAC9B,CAAA;AAED,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,UAAA;AAAA,IACAE,qBAAA,CAAW,eAAe,MAAM,CAAA;AAAA,IAChC,OAAO,KAAK,GAAA,KAAQ;AAClB,MAAA,MAAM,EAAE,QAAA,EAAU,cAAA,EAAgB,OAAA,EAAS,MAAA,KAAW,GAAA,CAAI,IAAA;AAE1D,MAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,WAAA,CAAY,GAAG,CAAA;AAClD,MAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,WAAW,CAAA;AAEhE,MAAA,MAAM,gBAAA,GAAmB,MAAM,IAAA,CAAK,MAAA,CAAO;AAAA,QACzC,OAAA;AAAA,QACA,QAAA;AAAA,QACA,cAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,GAAA,CAAI,IAAA,CAAK;AAAA,QACP,QAAA,EAAU,gBAAA;AAAA,QACV;AAAA,OACD,CAAA;AAAA,IACH;AAAA,GACF;AAEA,EAAA,MAAM,UAAA,GAAaF,mBAAE,MAAA,CAAO;AAAA,IAC1B,EAAA,EAAIA,kBAAA,CAAE,MAAA,EAAO,CAAE,IAAA;AAAK,GACrB,CAAA;AAED,EAAA,MAAA,CAAO,GAAA,CAAI,QAAQE,qBAAA,CAAW,UAAA,EAAY,QAAQ,CAAA,EAAG,OAAO,KAAK,GAAA,KAAQ;AACvE,IAAA,MAAM,EAAE,EAAA,EAAG,GAAI,GAAA,CAAI,MAAA;AAEnB,IAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,WAAA,CAAY,GAAG,CAAA;AAClD,IAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,WAAW,CAAA;AAEhE,IAAA,MAAM,YAAA,GAAe,MAAM,IAAA,CAAK,eAAA,CAAgB;AAAA,MAC9C,cAAA,EAAgB,EAAA;AAAA,MAChB;AAAA,KACD,CAAA;AAED,IAAA,GAAA,CAAI,IAAA,CAAK,EAAE,YAAA,EAAc,CAAA;AAAA,EAC3B,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;;;;"}
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var express = require('express');
|
|
4
3
|
var Router = require('express-promise-router');
|
|
5
4
|
|
|
6
5
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
7
6
|
|
|
8
|
-
var express__default = /*#__PURE__*/_interopDefaultCompat(express);
|
|
9
7
|
var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
|
|
10
8
|
|
|
11
9
|
async function createModelRouter(options) {
|
|
12
10
|
const { chat } = options;
|
|
13
11
|
const router = Router__default.default();
|
|
14
|
-
router.use(express__default.default.json());
|
|
15
12
|
router.get("/", async (_req, res) => {
|
|
16
13
|
const models = await chat.getAvailableModels();
|
|
17
14
|
res.json({ models });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.cjs.js","sources":["../../../src/services/router/models.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport { ChatService } from '../chat';\n\nexport type ModelRouterOptions = {\n chat: ChatService;\n};\n\nexport async function createModelRouter(\n options: ModelRouterOptions,\n): Promise<express.Router> {\n const { chat } = options;\n const router = Router();\n
|
|
1
|
+
{"version":3,"file":"models.cjs.js","sources":["../../../src/services/router/models.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport { ChatService } from '../chat';\n\nexport type ModelRouterOptions = {\n chat: ChatService;\n};\n\nexport async function createModelRouter(\n options: ModelRouterOptions,\n): Promise<express.Router> {\n const { chat } = options;\n const router = Router();\n\n router.get('/', async (_req, res) => {\n const models = await chat.getAvailableModels();\n res.json({ models });\n });\n\n return router;\n}\n"],"names":["Router"],"mappings":";;;;;;;;AAQA,eAAsB,kBACpB,OAAA,EACyB;AACzB,EAAA,MAAM,EAAE,MAAK,GAAI,OAAA;AACjB,EAAA,MAAM,SAASA,uBAAA,EAAO;AAEtB,EAAA,MAAA,CAAO,GAAA,CAAI,GAAA,EAAK,OAAO,IAAA,EAAM,GAAA,KAAQ;AACnC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,kBAAA,EAAmB;AAC7C,IAAA,GAAA,CAAI,IAAA,CAAK,EAAE,MAAA,EAAQ,CAAA;AAAA,EACrB,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sweetoburrito/backstage-plugin-ai-assistant-backend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
"role": "backend-plugin",
|
|
14
14
|
"pluginId": "ai-assistant",
|
|
15
15
|
"pluginPackages": [
|
|
16
|
+
"@sweetoburrito/backstage-plugin-ai-assistant",
|
|
16
17
|
"@sweetoburrito/backstage-plugin-ai-assistant-backend",
|
|
18
|
+
"@sweetoburrito/backstage-plugin-ai-assistant-common",
|
|
17
19
|
"@sweetoburrito/backstage-plugin-ai-assistant-node"
|
|
18
20
|
],
|
|
19
21
|
"features": {
|
|
@@ -34,8 +36,10 @@
|
|
|
34
36
|
"@backstage/backend-plugin-api": "backstage:^",
|
|
35
37
|
"@backstage/catalog-client": "backstage:^",
|
|
36
38
|
"@backstage/errors": "backstage:^",
|
|
39
|
+
"@backstage/plugin-signals-node": "backstage:^",
|
|
37
40
|
"@langchain/core": "^0.3.72",
|
|
38
41
|
"@langchain/textsplitters": "^0.1.0",
|
|
42
|
+
"@sweetoburrito/backstage-plugin-ai-assistant-common": "workspace:^",
|
|
39
43
|
"@sweetoburrito/backstage-plugin-ai-assistant-node": "workspace:^",
|
|
40
44
|
"express": "^4.17.1",
|
|
41
45
|
"express-promise-router": "^4.1.0",
|
|
@@ -46,7 +50,15 @@
|
|
|
46
50
|
"devDependencies": {
|
|
47
51
|
"@backstage/backend-test-utils": "backstage:^",
|
|
48
52
|
"@backstage/cli": "backstage:^",
|
|
53
|
+
"@backstage/plugin-auth-backend": "backstage:^",
|
|
54
|
+
"@backstage/plugin-auth-backend-module-guest-provider": "backstage:^",
|
|
55
|
+
"@backstage/plugin-catalog-backend": "backstage:^",
|
|
56
|
+
"@backstage/plugin-signals-backend": "backstage:^",
|
|
49
57
|
"@backstage/types": "backstage:^",
|
|
58
|
+
"@sweetoburrito/backstage-plugin-ai-assistant-backend-module-embeddings-provider-ollama": "workspace:^",
|
|
59
|
+
"@sweetoburrito/backstage-plugin-ai-assistant-backend-module-ingestor-catalog": "workspace:^",
|
|
60
|
+
"@sweetoburrito/backstage-plugin-ai-assistant-backend-module-model-provider-azure-ai": "workspace:^",
|
|
61
|
+
"@sweetoburrito/backstage-plugin-ai-assistant-backend-module-model-provider-ollama": "workspace:^",
|
|
50
62
|
"@types/express": "^4.0.0",
|
|
51
63
|
"@types/supertest": "^2.0.12",
|
|
52
64
|
"supertest": "^6.2.4"
|