fragment-ts 1.0.1 → 1.0.3
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/README.md +9 -9
- package/dist/cli/commands/diagnostics.command.js +2 -2
- package/dist/cli/commands/generate.command.js +3 -3
- package/dist/cli/commands/generate.command.js.map +1 -1
- package/dist/cli/commands/init.command.js +7 -7
- package/examples/blog-api/fragment.json +3 -7
- package/examples/blog-api/package-lock.json +3405 -0
- package/examples/blog-api/package.json +1 -1
- package/examples/blog-api/src/controllers/app.controller.ts +1 -1
- package/examples/blog-api/src/controllers/auth.controller.ts +1 -1
- package/examples/blog-api/src/controllers/category.controller.ts +1 -1
- package/examples/blog-api/src/controllers/comment.controller.ts +13 -9
- package/examples/blog-api/src/controllers/post.controller.ts +1 -1
- package/examples/blog-api/src/main.ts +3 -3
- package/examples/blog-api/src/repositories/category.repository.ts +1 -1
- package/examples/blog-api/src/repositories/comment.repository.ts +1 -1
- package/examples/blog-api/src/repositories/post.repository.ts +1 -1
- package/examples/blog-api/src/seeds/SampleData.seed.ts +1 -1
- package/examples/blog-api/src/services/app.service.ts +1 -1
- package/examples/blog-api/src/services/auth.service.ts +2 -2
- package/examples/blog-api/src/services/category.service.ts +1 -1
- package/examples/blog-api/src/services/comment.service.ts +1 -1
- package/examples/blog-api/src/services/post.service.ts +1 -1
- package/package.json +7 -8
- package/src/cli/commands/diagnostics.command.ts +2 -2
- package/src/cli/commands/generate.command.ts +3 -3
- package/src/cli/commands/init.command.ts +7 -7
- package/examples/ai-assistant/fragment.json +0 -18
- package/examples/ai-assistant/package-lock.json +0 -2921
- package/examples/ai-assistant/package.json +0 -20
- package/examples/ai-assistant/src/controllers/app.controller.ts +0 -9
- package/examples/ai-assistant/src/controllers/chat.controller.ts +0 -69
- package/examples/ai-assistant/src/controllers/conversation.controller.ts +0 -29
- package/examples/ai-assistant/src/controllers/message.controller.ts +0 -29
- package/examples/ai-assistant/src/controllers/search.controller.ts +0 -16
- package/examples/ai-assistant/src/dto/create-conversation.dto.ts +0 -6
- package/examples/ai-assistant/src/dto/create-message.dto.ts +0 -6
- package/examples/ai-assistant/src/entities/conversation.entity.ts +0 -23
- package/examples/ai-assistant/src/entities/message.entity.ts +0 -27
- package/examples/ai-assistant/src/entities/user.entity.ts +0 -16
- package/examples/ai-assistant/src/main.ts +0 -15
- package/examples/ai-assistant/src/migrations/1767738396740-CreateConversationTables.ts +0 -37
- package/examples/ai-assistant/src/repositories/conversation.repository.ts +0 -32
- package/examples/ai-assistant/src/repositories/message.repository.ts +0 -30
- package/examples/ai-assistant/src/services/ai.service.ts +0 -41
- package/examples/ai-assistant/src/services/app.service.ts +0 -8
- package/examples/ai-assistant/src/services/conversation.service.ts +0 -75
- package/examples/ai-assistant/src/services/message.service.ts +0 -27
- package/examples/ai-assistant/tsconfig.json +0 -23
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "ai-assistant",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"main": "dist/main.js",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"start": "node dist/main.js",
|
|
7
|
-
"dev": "fragment serve",
|
|
8
|
-
"build": "fragment build",
|
|
9
|
-
"test": "fragment test"
|
|
10
|
-
},
|
|
11
|
-
"dependencies": {
|
|
12
|
-
"fragment": "^1.0.0",
|
|
13
|
-
"reflect-metadata": "^0.1.13"
|
|
14
|
-
},
|
|
15
|
-
"devDependencies": {
|
|
16
|
-
"@types/node": "^20.10.5",
|
|
17
|
-
"ts-node": "^10.9.2",
|
|
18
|
-
"typescript": "^5.3.3"
|
|
19
|
-
}
|
|
20
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { Controller, Get, Post, Body, Param, Res } from "fragment";
|
|
2
|
-
import { ConversationService } from "../services/conversation.service";
|
|
3
|
-
import { Response } from "express";
|
|
4
|
-
|
|
5
|
-
@Controller("/api/chat")
|
|
6
|
-
export class ChatController {
|
|
7
|
-
constructor(private conversationService: ConversationService) {}
|
|
8
|
-
|
|
9
|
-
@Post("/conversations")
|
|
10
|
-
async createConversation(@Body() body: any) {
|
|
11
|
-
return this.conversationService.create(body.userId || 1, body.title);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
@Get("/conversations/:userId")
|
|
15
|
-
async getConversations(@Param("userId") userId: string) {
|
|
16
|
-
return this.conversationService.findByUser(parseInt(userId));
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
@Get("/conversations/:id/messages")
|
|
20
|
-
async getMessages(@Param("id") id: string) {
|
|
21
|
-
return this.conversationService.getMessages(parseInt(id));
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
@Post("/conversations/:id/message")
|
|
25
|
-
async sendMessage(@Param("id") id: string, @Body() body: any) {
|
|
26
|
-
return this.conversationService.chat(parseInt(id), body.message);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
@Post("/conversations/:id/stream")
|
|
30
|
-
async streamMessage(
|
|
31
|
-
@Param("id") id: string,
|
|
32
|
-
@Body() body: any,
|
|
33
|
-
@Res() res: Response,
|
|
34
|
-
) {
|
|
35
|
-
res.setHeader("Content-Type", "text/event-stream");
|
|
36
|
-
res.setHeader("Cache-Control", "no-cache");
|
|
37
|
-
res.setHeader("Connection", "keep-alive");
|
|
38
|
-
|
|
39
|
-
let fullResponse = "";
|
|
40
|
-
|
|
41
|
-
await this.conversationService.addMessage(
|
|
42
|
-
parseInt(id),
|
|
43
|
-
"user",
|
|
44
|
-
body.message,
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
const messages = await this.conversationService.getMessages(parseInt(id));
|
|
48
|
-
const aiMessages = messages.map((m: any) => ({
|
|
49
|
-
role: m.role as any,
|
|
50
|
-
content: m.content,
|
|
51
|
-
}));
|
|
52
|
-
|
|
53
|
-
const aiService = (this.conversationService as any).aiService;
|
|
54
|
-
|
|
55
|
-
await aiService.streamChat(aiMessages, (chunk: string) => {
|
|
56
|
-
fullResponse += chunk;
|
|
57
|
-
res.write(`data: ${JSON.stringify({ chunk })}\n\n`);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
await this.conversationService.addMessage(
|
|
61
|
-
parseInt(id),
|
|
62
|
-
"assistant",
|
|
63
|
-
fullResponse,
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
res.write("data: [DONE]\n\n");
|
|
67
|
-
res.end();
|
|
68
|
-
}
|
|
69
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Controller, Get, Post, Put, Delete, Body, Param } from 'fragment';
|
|
2
|
-
|
|
3
|
-
@Controller('/conversation')
|
|
4
|
-
export class ConversationController {
|
|
5
|
-
@Get()
|
|
6
|
-
findAll() {
|
|
7
|
-
return [];
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
@Get('/:id')
|
|
11
|
-
findOne(@Param('id') id: string) {
|
|
12
|
-
return { id };
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
@Post()
|
|
16
|
-
create(@Body() body: any) {
|
|
17
|
-
return body;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
@Put('/:id')
|
|
21
|
-
update(@Param('id') id: string, @Body() body: any) {
|
|
22
|
-
return { id, ...body };
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
@Delete('/:id')
|
|
26
|
-
delete(@Param('id') id: string) {
|
|
27
|
-
return { deleted: true, id };
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Controller, Get, Post, Put, Delete, Body, Param } from 'fragment';
|
|
2
|
-
|
|
3
|
-
@Controller('/message')
|
|
4
|
-
export class MessageController {
|
|
5
|
-
@Get()
|
|
6
|
-
findAll() {
|
|
7
|
-
return [];
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
@Get('/:id')
|
|
11
|
-
findOne(@Param('id') id: string) {
|
|
12
|
-
return { id };
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
@Post()
|
|
16
|
-
create(@Body() body: any) {
|
|
17
|
-
return body;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
@Put('/:id')
|
|
21
|
-
update(@Param('id') id: string, @Body() body: any) {
|
|
22
|
-
return { id, ...body };
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
@Delete('/:id')
|
|
26
|
-
delete(@Param('id') id: string) {
|
|
27
|
-
return { deleted: true, id };
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Controller, Post, Body, Query } from "fragment";
|
|
2
|
-
import { ConversationService } from "../services/conversation.service";
|
|
3
|
-
|
|
4
|
-
@Controller("/api/search")
|
|
5
|
-
export class SearchController {
|
|
6
|
-
constructor(private conversationService: ConversationService) {}
|
|
7
|
-
|
|
8
|
-
@Post("/semantic")
|
|
9
|
-
async semanticSearch(
|
|
10
|
-
@Body() body: any,
|
|
11
|
-
@Query("conversationId") conversationId?: string,
|
|
12
|
-
) {
|
|
13
|
-
const convId = conversationId ? parseInt(conversationId) : undefined;
|
|
14
|
-
return this.conversationService.semanticSearch(body.query, convId);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm';
|
|
2
|
-
import { Message } from './message.entity';
|
|
3
|
-
|
|
4
|
-
@Entity()
|
|
5
|
-
export class Conversation {
|
|
6
|
-
@PrimaryGeneratedColumn()
|
|
7
|
-
id!: number;
|
|
8
|
-
|
|
9
|
-
@Column()
|
|
10
|
-
title!: string;
|
|
11
|
-
|
|
12
|
-
@Column()
|
|
13
|
-
userId!: number;
|
|
14
|
-
|
|
15
|
-
@OneToMany(() => Message, message => message.conversation)
|
|
16
|
-
messages!: Message[];
|
|
17
|
-
|
|
18
|
-
@Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
|
|
19
|
-
createdAt!: Date;
|
|
20
|
-
|
|
21
|
-
@Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
|
|
22
|
-
updatedAt!: Date;
|
|
23
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
|
|
2
|
-
import { Conversation } from './conversation.entity';
|
|
3
|
-
|
|
4
|
-
@Entity()
|
|
5
|
-
export class Message {
|
|
6
|
-
@PrimaryGeneratedColumn()
|
|
7
|
-
id!: number;
|
|
8
|
-
|
|
9
|
-
@Column()
|
|
10
|
-
conversationId!: number;
|
|
11
|
-
|
|
12
|
-
@ManyToOne(() => Conversation, conversation => conversation.messages)
|
|
13
|
-
@JoinColumn({ name: 'conversationId' })
|
|
14
|
-
conversation!: Conversation;
|
|
15
|
-
|
|
16
|
-
@Column()
|
|
17
|
-
role!: string;
|
|
18
|
-
|
|
19
|
-
@Column('text')
|
|
20
|
-
content!: string;
|
|
21
|
-
|
|
22
|
-
@Column('simple-json', { nullable: true })
|
|
23
|
-
embedding!: number[];
|
|
24
|
-
|
|
25
|
-
@Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
|
|
26
|
-
createdAt?: Date;
|
|
27
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
|
|
2
|
-
|
|
3
|
-
@Entity()
|
|
4
|
-
export class User {
|
|
5
|
-
@PrimaryGeneratedColumn()
|
|
6
|
-
id!: number;
|
|
7
|
-
|
|
8
|
-
@Column()
|
|
9
|
-
email!: string;
|
|
10
|
-
|
|
11
|
-
@Column()
|
|
12
|
-
name!: string;
|
|
13
|
-
|
|
14
|
-
@Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
|
|
15
|
-
createdAt?: Date;
|
|
16
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import 'reflect-metadata';
|
|
2
|
-
import { FragmentApplication } from 'fragment';
|
|
3
|
-
import { FragmentWebApplication } from 'fragment';
|
|
4
|
-
|
|
5
|
-
@FragmentApplication({
|
|
6
|
-
port: 3000,
|
|
7
|
-
})
|
|
8
|
-
class Application {}
|
|
9
|
-
|
|
10
|
-
async function bootstrap() {
|
|
11
|
-
const app = new FragmentWebApplication();
|
|
12
|
-
await app.bootstrap(Application);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
bootstrap();
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { MigrationInterface, QueryRunner, Table } from "typeorm";
|
|
2
|
-
|
|
3
|
-
export class CreateConversationTables1234567890 implements MigrationInterface {
|
|
4
|
-
async up(queryRunner: QueryRunner): Promise<void> {
|
|
5
|
-
await queryRunner.createTable(
|
|
6
|
-
new Table({
|
|
7
|
-
name: "conversation",
|
|
8
|
-
columns: [
|
|
9
|
-
{ name: "id", type: "integer", isPrimary: true, isGenerated: true },
|
|
10
|
-
{ name: "title", type: "varchar" },
|
|
11
|
-
{ name: "userId", type: "integer" },
|
|
12
|
-
{ name: "createdAt", type: "datetime", default: "CURRENT_TIMESTAMP" },
|
|
13
|
-
{ name: "updatedAt", type: "datetime", default: "CURRENT_TIMESTAMP" },
|
|
14
|
-
],
|
|
15
|
-
}),
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
await queryRunner.createTable(
|
|
19
|
-
new Table({
|
|
20
|
-
name: "message",
|
|
21
|
-
columns: [
|
|
22
|
-
{ name: "id", type: "integer", isPrimary: true, isGenerated: true },
|
|
23
|
-
{ name: "conversationId", type: "integer" },
|
|
24
|
-
{ name: "role", type: "varchar" },
|
|
25
|
-
{ name: "content", type: "text" },
|
|
26
|
-
{ name: "embedding", type: "text", isNullable: true },
|
|
27
|
-
{ name: "createdAt", type: "datetime", default: "CURRENT_TIMESTAMP" },
|
|
28
|
-
],
|
|
29
|
-
}),
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async down(queryRunner: QueryRunner): Promise<void> {
|
|
34
|
-
await queryRunner.dropTable("message");
|
|
35
|
-
await queryRunner.dropTable("conversation");
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { Repository } from "fragment";
|
|
2
|
-
import { Conversation } from "../entities/conversation.entity";
|
|
3
|
-
|
|
4
|
-
@Repository()
|
|
5
|
-
export class ConversationRepository {
|
|
6
|
-
async findAll(): Promise<Conversation[]> {
|
|
7
|
-
return [];
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async findById(id: number): Promise<Conversation | null> {
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async create(data: Partial<Conversation>): Promise<Conversation> {
|
|
15
|
-
return data as Conversation;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async update(
|
|
19
|
-
id: number,
|
|
20
|
-
data: Partial<Conversation>,
|
|
21
|
-
): Promise<Conversation | null> {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async delete(id: number): Promise<boolean> {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async findByUser(userId: number): Promise<Conversation[]> {
|
|
30
|
-
return [];
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Repository } from "fragment";
|
|
2
|
-
import { Message } from "../entities/message.entity";
|
|
3
|
-
import { Conversation } from "../entities/conversation.entity";
|
|
4
|
-
|
|
5
|
-
@Repository()
|
|
6
|
-
export class MessageRepository {
|
|
7
|
-
async findAll(): Promise<Message[]> {
|
|
8
|
-
return [];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async findById(id: number): Promise<Message | null> {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async create(data: Partial<Message>): Promise<Message> {
|
|
16
|
-
return data as Message;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async update(id: number, data: Partial<Message>): Promise<Message | null> {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async delete(id: number): Promise<boolean> {
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async findByConversation(conversationId: number): Promise<Conversation[]> {
|
|
28
|
-
return [];
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { Service } from 'fragment';
|
|
2
|
-
import { AIModule } from 'fragment';
|
|
3
|
-
|
|
4
|
-
@Service()
|
|
5
|
-
export class AIService {
|
|
6
|
-
private aiModule: AIModule;
|
|
7
|
-
|
|
8
|
-
constructor() {
|
|
9
|
-
this.aiModule = new AIModule({
|
|
10
|
-
openaiKey: process.env.OPENAI_API_KEY,
|
|
11
|
-
ollamaUrl: process.env.OLLAMA_URL
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async chat(messages: any[]) {
|
|
16
|
-
return this.aiModule.complete(messages, {
|
|
17
|
-
model: 'gpt-3.5-turbo',
|
|
18
|
-
temperature: 0.7,
|
|
19
|
-
maxTokens: 1000
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async streamChat(messages: any[], onChunk: (chunk: string) => void) {
|
|
24
|
-
await this.aiModule.streamComplete(messages, {
|
|
25
|
-
model: 'gpt-3.5-turbo',
|
|
26
|
-
temperature: 0.7
|
|
27
|
-
}, onChunk);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async generateEmbedding(text: string): Promise<number[]> {
|
|
31
|
-
const embeddings = await this.aiModule.embeddings([text]);
|
|
32
|
-
return embeddings[0];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
cosineSimilarity(a: number[], b: number[]): number {
|
|
36
|
-
const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
|
|
37
|
-
const magnitudeA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
|
|
38
|
-
const magnitudeB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
|
|
39
|
-
return dotProduct / (magnitudeA * magnitudeB);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { Service } from "fragment";
|
|
2
|
-
import { ConversationRepository } from "../repositories/conversation.repository";
|
|
3
|
-
import { MessageRepository } from "../repositories/message.repository";
|
|
4
|
-
import { AIService } from "./ai.service";
|
|
5
|
-
|
|
6
|
-
@Service()
|
|
7
|
-
export class ConversationService {
|
|
8
|
-
constructor(
|
|
9
|
-
private conversationRepository: ConversationRepository,
|
|
10
|
-
private messageRepository: MessageRepository,
|
|
11
|
-
private aiService: AIService,
|
|
12
|
-
) {}
|
|
13
|
-
|
|
14
|
-
async create(userId: number, title: string) {
|
|
15
|
-
return this.conversationRepository.create({ userId, title });
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async findByUser(userId: number) {
|
|
19
|
-
return this.conversationRepository.findByUser(userId);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async addMessage(conversationId: number, role: string, content: string) {
|
|
23
|
-
const embedding = await this.aiService.generateEmbedding(content);
|
|
24
|
-
|
|
25
|
-
return this.messageRepository.create({
|
|
26
|
-
conversationId,
|
|
27
|
-
role,
|
|
28
|
-
content,
|
|
29
|
-
embedding,
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async getMessages(conversationId: number) {
|
|
34
|
-
return this.messageRepository.findByConversation(conversationId);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async chat(conversationId: number, userMessage: string) {
|
|
38
|
-
await this.addMessage(conversationId, "user", userMessage);
|
|
39
|
-
|
|
40
|
-
const messages = await this.getMessages(conversationId);
|
|
41
|
-
const aiMessages = messages.map((m:any) => ({
|
|
42
|
-
role: m.role as any,
|
|
43
|
-
content: m.content,
|
|
44
|
-
}));
|
|
45
|
-
|
|
46
|
-
const response = await this.aiService.chat(aiMessages);
|
|
47
|
-
|
|
48
|
-
await this.addMessage(conversationId, "assistant", response);
|
|
49
|
-
|
|
50
|
-
return { response };
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async semanticSearch(query: string, conversationId?: number) {
|
|
54
|
-
const queryEmbedding = await this.aiService.generateEmbedding(query);
|
|
55
|
-
|
|
56
|
-
let messages = await this.messageRepository.findAll();
|
|
57
|
-
|
|
58
|
-
if (conversationId) {
|
|
59
|
-
messages = messages.filter((m) => m.conversationId === conversationId);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const results = messages
|
|
63
|
-
.map((message) => ({
|
|
64
|
-
message,
|
|
65
|
-
similarity: this.aiService.cosineSimilarity(
|
|
66
|
-
queryEmbedding,
|
|
67
|
-
message.embedding || [],
|
|
68
|
-
),
|
|
69
|
-
}))
|
|
70
|
-
.sort((a, b) => b.similarity - a.similarity)
|
|
71
|
-
.slice(0, 5);
|
|
72
|
-
|
|
73
|
-
return results;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Service } from 'fragment';
|
|
2
|
-
import { MessageRepository } from '../repositories/message.repository';
|
|
3
|
-
|
|
4
|
-
@Service()
|
|
5
|
-
export class MessageService {
|
|
6
|
-
constructor(private messageRepository: MessageRepository) {}
|
|
7
|
-
|
|
8
|
-
async findAll() {
|
|
9
|
-
return [];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
async findOne(id: string) {
|
|
13
|
-
return { id };
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async create(data: any) {
|
|
17
|
-
return data;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async update(id: string, data: any) {
|
|
21
|
-
return { id, ...data };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async delete(id: string) {
|
|
25
|
-
return { deleted: true, id };
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"lib": [
|
|
6
|
-
"ES2020"
|
|
7
|
-
],
|
|
8
|
-
"outDir": "./dist",
|
|
9
|
-
"rootDir": "./src",
|
|
10
|
-
"strict": true,
|
|
11
|
-
"esModuleInterop": true,
|
|
12
|
-
"experimentalDecorators": true,
|
|
13
|
-
"emitDecoratorMetadata": true,
|
|
14
|
-
"skipLibCheck": true
|
|
15
|
-
},
|
|
16
|
-
"include": [
|
|
17
|
-
"src/**/*"
|
|
18
|
-
],
|
|
19
|
-
"exclude": [
|
|
20
|
-
"node_modules",
|
|
21
|
-
"dist"
|
|
22
|
-
]
|
|
23
|
-
}
|