Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions integration/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# dependencies (bun install)
node_modules

# output
out
dist
*.tgz

# code coverage
coverage
*.lcov

# logs
logs
_.log
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# caches
.eslintcache
.cache
*.tsbuildinfo

# IntelliJ based IDEs
.idea

# Finder (MacOS) folder config
.DS_Store
15 changes: 15 additions & 0 deletions integration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# integration

To install dependencies:

```bash
bun install
```

To run:

```bash
bun run index.ts
```

This project was created using `bun init` in bun v1.2.13. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
25 changes: 25 additions & 0 deletions integration/bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 69 additions & 0 deletions integration/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
version: '3.3'
services:
postgres-container:
image: postgres
restart: always
environment:
POSTGRES_PASSWORD: your_password
ports:
- 5432:5432
volumes:
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
interval: 5s
retries: 5
start_period: 30s
# psql -h localhost -p 5432 -U postgres
end:
image: sixwaaaay/end:0.25.5
restart: always
ports:
- 5151:5151
environment:
ConnectionStrings__Default: "Host=postgres-container;Username=postgres;Password=your_password"
ConnectionStrings__ReplicationConnection: "Host=postgres-container;Username=postgres;Password=your_password"
Application__Secret: "the secret key|the secret key|the secret key"
ASPNETCORE_URLS: "http://+:5151"
depends_on:
postgres-container:
condition: service_healthy
meilisearch:
image: getmeili/meilisearch:v1.15
environment:
MEILI_MASTER_KEY: masterKey|masterKey|masterKey|masterKey
ports:
- 7700:7700
qdrant:
image: qdrant/qdrant:v1.15
environment:
QDRANT__SERVICE__API_KEY: qdrant|qdrant|qdrant|qdrant|qdrant|qdrant
ports:
- 6333:6333
valkey:
image: valkey/valkey:8-alpine3.22 # redis alternative
ports:
- 6379:6379
content:
image: sixwaaaay/content:latest
ports:
- 5000:5000
environment:
ConnectionStrings__Default: "Host=postgres-container;Username=postgres;Password=your_password"
ConnectionStrings__User: "http://end:5151"
ConnectionStrings__Vote: "http://end:5151"
ConnectionStrings__Search: "http://meilisearch:7700"
ConnectionStrings__Redis: "valkey:6379"
ConnectionStrings__QdrantUrl: "http://qdrant:6334"
ConnectionStrings__QdrantApiKey: "qdrant|qdrant|qdrant|qdrant|qdrant|qdrant"
Secret: "the secret key|the secret key|the secret key"
Token: "masterKey|masterKey|masterKey|masterKey"
bunserver:
image: oven/bun:1
command: "bun embeddingserver.ts"
ports:
- "8000:8000"
volumes:
- ./embeddingserver.ts:/app/embeddingserver.ts
working_dir: /app
restart: always
112 changes: 112 additions & 0 deletions integration/embeddingserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// 定义响应结构
type EmbeddingData = {
object: "embedding";
embedding: number[];
index: number;
};

type EmbeddingResponse = {
object: "list";
data: EmbeddingData[];
model: string;
usage: {
prompt_tokens: number;
total_tokens: number;
};
};

// 定义支持的模型及其维度
const modelDimensions: Record<string, number> = {
"text-embedding-ada-002": 1536,
"text-similarity-ada-001": 1024,
"text-search-ada-001": 1024,
"code-search-ada-code-001": 1024,
"simple-vector": 24
};

// 生成随机嵌入向量
function generateEmbedding(dimensions: number): number[] {
return Array.from({ length: dimensions }, () => Math.random() * 2 - 1);
}

// 简单的 token 计数器
function countTokens(text: string | string[]): number {
if (Array.isArray(text)) {
return text.reduce((acc, t) => acc + countTokens(t), 0);
}
return text.split(/\s+/).length;
}

// 创建 HTTP 服务器
const server = Bun.serve({
port: 8000,
fetch(req) {
const url = new URL(req.url);

// 处理 Embedding API 请求
if (req.method === "POST" && url.pathname === "/v1/embeddings") {
return handleEmbeddingRequest(req);
}

// 默认返回 404
return new Response(JSON.stringify({ error: "Not Found" }), {
status: 404,
headers: { "Content-Type": "application/json" },
});
},
});

// 处理嵌入请求
async function handleEmbeddingRequest(req: Request): Promise<Response> {
try {
// 解析请求体
const { input, model = "text-embedding-ada-002" } = await req.json();

// 验证输入
if (input === undefined) {
return new Response(JSON.stringify({ error: "Missing 'input' parameter" }), {
status: 400,
headers: { "Content-Type": "application/json" },
});
}

// 确保 input 是数组
const inputList = Array.isArray(input) ? input : [input];

// 获取模型维度
const dimensions = modelDimensions[model] || 1536;

// 生成嵌入向量
const data = inputList.map((text, index) => ({
object: "embedding",
embedding: generateEmbedding(dimensions),
index,
})) as EmbeddingData[];

// 计算 token 使用量
const promptTokens = countTokens(inputList);

// 构建响应
const response: EmbeddingResponse = {
object: "list",
data,
model,
usage: {
prompt_tokens: promptTokens,
total_tokens: promptTokens,
},
};

return new Response(JSON.stringify(response), {
headers: { "Content-Type": "application/json" },
});
} catch (error) {
console.error("Error handling request:", error);
return new Response(JSON.stringify({ error: "Internal Server Error" }), {
status: 500,
headers: { "Content-Type": "application/json" },
});
}
}

console.log(`Server running at http://localhost:${server.port}`);
1 change: 1 addition & 0 deletions integration/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("the integration via Bun!");
82 changes: 82 additions & 0 deletions integration/init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
CREATE TABLE users (
id bigserial,
name character varying(255) NOT NULL,
email character varying(255) NOT NULL,
code character varying(6) NOT NULL DEFAULT ''::character varying,
code_time timestamptz NOT NULL DEFAULT to_timestamp('2020-01-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text),
code_try integer NOT NULL DEFAULT 0,
bio character varying(255) NOT NULL DEFAULT ''::character varying,
avatar character varying(255) NOT NULL DEFAULT ''::character varying,
created_at timestamptz NOT NULL DEFAULT now(),
background character varying(255) NOT NULL DEFAULT ''::character varying,
PRIMARY KEY (id),
UNIQUE (email)
);


-- 一个脚本,生成 10 万 条数据
INSERT INTO users (name, email, code, code_time, code_try, bio, avatar, created_at, background)
SELECT
'user_' || i::text,
'user_' || i::text || '@example.com',
'123456',
now(),
0,
'This is a bio for user ' || i::text,
'https://example.com/avatar_' || i::text || '.jpg',
now(),
'https://example.com/background_' || i::text || '.jpg'
FROM generate_series(1, 100000) AS s(i);

CREATE TABLE graph (
id bigserial,
relation integer NOT NULL,
subject_id bigint NOT NULL,
object_id bigint NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (id),
UNIQUE (relation, subject_id, object_id)
);

-- 一个脚本,生成 10 万 条数据
INSERT INTO graph (relation, subject_id, object_id)
SELECT-- 从序列获取下一个值作为 id
floor(random() * 3) + 1, -- 生成 1 到 3 之间的随机整数
floor(random() * 100000) + 1, -- 生成 1 到 100000 之间的随机整数
floor(random() * 100000) + 1 -- 生成 1 到 100000 之间的随机整数
FROM generate_series(1, 100000) AS s(i)
ON CONFLICT (relation, subject_id, object_id) DO NOTHING;



CREATE TABLE videos (
id bigserial,
user_id bigint NOT NULL,
title character varying(255) NOT NULL,
des text NOT NULL,
cover_url character varying(255) DEFAULT ''::character varying NOT NULL,
video_url character varying(255) DEFAULT ''::character varying NOT NULL,
duration integer,
view_count integer DEFAULT 0 NOT NULL,
like_count integer DEFAULT 0 NOT NULL,
created_at timestamptz DEFAULT now() NOT NULL,
updated_at timestamptz DEFAULT now() NOT NULL,
processed integer DEFAULT 0 NOT NULL,
PRIMARY KEY (id)
);

-- 一个脚本,生成 10 万 条数据
INSERT INTO videos (user_id, title, des, cover_url, video_url, duration, view_count, like_count, created_at, updated_at, processed)
SELECT
floor(random() * 100000) + 1, -- 生成 1 到 100000 之间的随机整数
'Video ' || i::text,
'This is a description for video ' || i::text,
'https://example.com/cover_' || i::text || '.jpg',
'https://example.com/video_' || i::text || '.mp4',
floor(random() * 3600) + 1, -- 生成 1 到 3600 之间的随机整数
floor(random() * 10000) + 1, -- 生成 1 到 10000 之间的随机整数
floor(random() * 1000) + 1, -- 生成 1 到 1000 之间的随机整数
now(),
now(),
floor(random() * 2) -- 生成 0 或 1
FROM generate_series(1, 100000) AS s(i);
Loading
Loading