Flutter轻量级嵌入Dart服务器插件lite_embeddings_dart_server的使用
Flutter轻量级嵌入Dart服务器插件lite_embeddings_dart_server的使用
特性
- 支持向量数据库:Chroma
- 支持文件类型:纯文本,包括
Markdown
和TXT
- 是Dart List Embeddings的HTTP API封装
- 基于Lite Embeddings Dart的EmbeddingsService(包含DTO),添加了Controller、Router,并封装为HTTP/WS API。
使用方法
1. 准备工作
- 文档文件,根据
/example/docs/*.md
- 文件中的分隔符
- 如果是
markdown
文件,推荐使用<!--SEPARATOR-->
作为分隔符,以便在渲染后不显示它。
- 如果是
- 在
example
文件夹中添加.env
文件,并在.env
文件中添加以下内容:baseUrl = https://xxx.xxx.com # LLM API BaseURL apiKey = sk-xxxxxxxxxxxxxxxxxxxx # LLM API ApiKey
2. 开发并运行服务器
- 在
debug
或run
模式下运行/bin/server.dart
文件的main()
方法。
3. HTTP API
- 包含以下API:
3.1 HTTP API
[GET] /version
- 功能:获取版本号,确认服务是否运行
- 请求参数:无
- 响应体示例:
{ "version": "0.1.0" }
[POST] /docs/create-by-text
- 功能:创建文档嵌入,提交整个文本和分隔符,服务将分割并写入向量数据库
- 请求参数:
- 文档信息:文档名称、文本、分隔符、元数据、LLM 配置
- 关于元数据:可选,每个段落相同的元数据。默认元数据包括
vdb
和embeddings_model
。 - 示例:
{ "docsName": "<Docs name, e.g. Moore's Law for Everything.md>", "text": "<Docs full text, with separetor>", "separator": "<Separator text>", "metadata": "<Optional, in each segment, json map, value only int, float, string, bool, NOT support object and array. Each segment with same metadata>", "llmConfig": { "baseUrl": "<LLM API baseUrl, e.g. https://api.openai.com/v1>", "apiKey": "<LLM API apiKey, e.g. sk-xxxxxxxxxx>", "model": "<LLM API embeddings model name, e.g. text-embedding-ada-002>" } }
- 响应体:
- 创建成功的文档信息:文档ID、文档名称、Token 使用情况
- 响应体示例:
{ "docsId": "<Docs Id>", "docsName": "<Docs Name>", "tokenUsage": { "promptToken": "", "totalToken": "" } }
[POST] /docs/create
- 功能:创建文档嵌入,提交已拆分的文档,服务将写入向量数据库
- 请求参数:
- 文档信息:文档名称、段落和元数据数组、LLM 配置
- 关于元数据:可选,默认元数据包括
vdb
和embeddings_model
。 - 示例:
{ "docsName": "<Docs name, e.g. Moore's Law for Everything.md>", "segmentList": [ { "text": "<Segment text>", "metadata": "<Optional, json map, value only int, float, string, bool, NOT support object and array>" } ], "llmConfig": { "baseUrl": "<LLM API baseUrl, e.g. https://api.openai.com/v1>", "apiKey": "<LLM API apiKey, e.g. sk-xxxxxxxxxx>", "model": "<LLM API embeddings model name, e.g. text-embedding-ada-002>" } }
- 响应体:
- 创建成功的文档信息:文档ID、文档名称、Token 使用情况
- 响应体示例:
{ "docsId": "<Docs Id>", "docsName": "<Docs Name>", "tokenUsage": { "promptToken": "", "totalToken": "" } }
[POST] /docs/delete
- 功能:删除文档,提交文档ID
- 请求参数:
- 文档ID
- 示例:
{ "docsId": "xxxxxxxx" }
- 响应体:
- 删除的文档信息:文档ID
- 响应体示例:
{ "docsId": "xxxxxxxx" }
[GET] /docs/list
- 功能:列出所有文档,返回文档ID和文档名称数组
- 请求参数:无
- 响应体:
- 文档信息列表:文档ID和文档名称
- 响应体示例:
[ { "docsId": "<Docs Id>", "docsName": "<Docs Name>" } ]
[POST] /docs/rename
- 功能:重命名文档名称
- 请求参数:
- 文档ID、新的文档名称
- 示例:
{ "docsId": "<Docs Id>", "docsName": "<Docs Name>" }
- 响应体:
- 修改后的文档信息:文档ID和文档名称
- 响应体示例:
{ "docsId": "<Docs Id>", "docsName": "<Docs Name>" }
[POST] /docs/query
- 功能:文本查询,返回按距离排序的N个段落数组
- 请求参数:
- 文档ID、查询文本、返回查询结果数量、LLM 配置
- 示例:
{ "docsId": "xxxxxxxx", "queryText": "<query text string>", "nResults": "<UInt, return query result by sort number>", "llmConfig": { "baseUrl": "<LLM API baseUrl, e.g. https://api.openai.com/v1>", "apiKey": "<LLM API apiKey, e.g. sk-xxxxxxxxxx>", "model": "<LLM API embeddings model name, e.g. text-embedding-ada-002>" } }
- 响应体:
- 文档ID、段落结果列表、Token 使用情况
- 响应体示例:
{ "docsId": "xxxxxxxx", "segmentResultList": [ { "segmentId": "<Segment Id>", "text": "<Segment text>", "metadata": "<json map, segment with>", "distance": "<0.x float, segment match distance, smaller means closer>" } ], "tokenUsage": { "promptToken": "", "totalToken": "" } }
[POST] /docs/batch-query
- 功能:文本数组查询,一次查询多个文本,返回N个段落数组
- 请求参数:
- 文档ID、查询文本数组、返回查询结果数量、LLM 配置
- 示例:
{ "docsId": "xxxxxxxx", "queryTextList": [ "<Query Text 1>", "<Query Text 2>" ], "nResults": "<UInt, return query result by sort number>", "llmConfig": { "baseUrl": "<LLM API baseUrl, e.g. https://api.openai.com/v1>", "apiKey": "<LLM API apiKey, e.g. sk-xxxxxxxxxx>", "model": "<LLM API embeddings model name, e.g. text-embedding-ada-002>" } }
- 响应体:
- 查询结果:文档ID、段落结果数组、Token 使用情况
- 响应体示例:
[ { "docsId": "xxxxxxxx", "segmentResultList": [ { "segmentId": "<Segment Id>", "text": "<Segment text>", "metadata": "<json map, segment with>", "distance": "<0.x float, segment match distance, smaller means closer>" } ], "tokenUsage": { "promptToken": "", "totalToken": "" } } ]
[POST] /docs/multi-query
- 功能:文档数组查询,用一个文本查询多个文档,返回N个段落和文档ID数组
- 请求参数:
- 文档ID数组、查询文本、返回查询结果数量
- 示例:
{ "docsIdList": ["xxxxxxxx", "yyyyyyyy"], "queryText": "<Query Text 1>", "nResults": "<UInt, return query result by sort number>", "removeDuplicates": "<(Optional)boolean, default:true, return segments will be removed if same text>", "llmConfig": { "baseUrl": "<LLM API baseUrl, e.g. https://api.openai.com/v1>", "apiKey": "<LLM API apiKey, e.g. sk-xxxxxxxxxx>", "model": "<LLM API embeddings model name, e.g. text-embedding-ada-002>" } }
- 响应体:
- 查询结果:段落信息数组,包括文档ID、段落ID、段落文本、元数据、距离
- 响应体示例:
{ "segmentResultList": [ { "docsId": "xxxxxxxx", "segmentId": "<Segment Id>", "text": "<Segment text>", "metadata": "<json map, segment with>", "distance": "<0.x float, segment match distance, smaller means closer>" } ], "tokenUsage": { "promptToken": "", "totalToken": "" } }
[POST] /segment/list
- 功能:列出文档中的所有段落
- 请求参数:
- 文档ID
- 示例:
{ "docsId": "xxxxxxxx" }
- 响应体:
- 文档ID、文档名称、段落信息列表
- 响应体示例:
{ "docsId": "xxxxxxxx", "docsName": "<Docs Name>", "segmentInfoList": [ { "SegmentId": "<Segment Id>", "text": "<Segment text>", "metadata": "<json map, segment with>" } ] }
[POST] /segment/insert
- 功能:通过索引插入段落。如果没有索引,则新段落将被插入到最后
- 请求参数:
- 文档ID、新段落、索引、LLM 配置
- 关于元数据:可选,默认元数据包括
vdb
和embeddings_model
。 - 示例:
{ "docsId": "xxxxxxxx", "segment": { "text": "<Segment text>", "metadata": "<Optional, json map, segment with>" }, "index": "(Optional) UInt, if null or large than length, be inserted at last", "llmConfig": { "baseUrl": "<LLM API baseUrl, e.g. https://api.openai.com/v1>", "apiKey": "<LLM API apiKey, e.g. sk-xxxxxxxxxx>", "model": "<LLM API embeddings model name, e.g. text-embedding-ada-002>" } }
- 响应体:
- 新段落ID、Token 使用情况
- 响应体示例:
{ "segmentId": "xxxxxxxx", "tokenUsage": { "promptToken": "", "totalToken": "" } }
[POST] /segment/update
- 功能:更新段落
- 请求参数:
- 文档ID、段落、LLM 配置
- 关于元数据,可选:
<null>
:不更新当前元数据{}
:清除元数据,但保留默认元数据包括vdb
和embeddings_model
- 值:添加或更新当前元数据
- 示例:
{ "docsId": "xxxxxxxx", "segment": { "segmentId": "Segment Id", "text": "<Segment text>", "metadata": "<Optional, json map, segment with>" }, "llmConfig": { "baseUrl": "<LLM API baseUrl, e.g. https://api.openai.com/v1>", "apiKey": "<LLM API apiKey, e.g. sk-xxxxxxxxxx>", "model": "<LLM API embeddings model name, e.g. text-embedding-ada-002>" } }
- 响应体:
- 段落ID、Token 使用情况
- 响应体示例:
{ "segmentId": "xxxxxxxx", "tokenUsage": { "promptToken": "", "totalToken": "" } }
[POST] /segment/delete
- 功能:删除段落
- 请求参数:
- 要删除的段落的文档ID和段落ID
- 示例:
{ "docsId": "xxxxxxxx", "segmentId": "xxxxxxxx" }
- 响应体:
- 段落ID
- 响应体示例:
{ "segmentId": "xxxxxxxx" }
构建和运行
- 在shell脚本中构建:
dart compile exe bin/server.dart -o build/lite_embeddings_dart_server
- 然后,
lite_embeddings_dart_server
文件将在build
文件夹中。 - 将
config.json
文件复制到lite_embeddings_dart_server
的同一文件夹中。 - 在shell脚本中运行:
./lite_embeddings_dart_server
- 终端将显示:
INFO: 2024-06-24 14:48:05.862057: PID 34567: [HTTP] Start Server - http://0.0.0.0:9537/api
更多关于Flutter轻量级嵌入Dart服务器插件lite_embeddings_dart_server的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter轻量级嵌入Dart服务器插件lite_embeddings_dart_server的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
lite_embeddings_dart_server
是一个轻量级的 Dart 服务器插件,旨在简化在 Flutter 应用中嵌入本地服务器的过程。它允许你在 Flutter 应用中运行一个简单的 Dart 服务器,以便处理 HTTP 请求、WebSocket 通信等。
主要特点
- 轻量级: 该插件设计简洁,专注于提供基本的功能,适合小型项目或快速原型开发。
- 易于集成: 与 Flutter 应用无缝集成,无需复杂的配置。
- 支持 HTTP 和 WebSocket: 提供基本的 HTTP 请求处理和 WebSocket 通信功能。
使用步骤
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 lite_embeddings_dart_server
依赖:
dependencies:
flutter:
sdk: flutter
lite_embeddings_dart_server: ^0.1.0 # 请使用最新版本
然后运行 flutter pub get
来获取依赖。
2. 启动服务器
在你的 Flutter 应用中,你可以通过以下代码启动一个简单的 Dart 服务器:
import 'package:lite_embeddings_dart_server/lite_embeddings_dart_server.dart';
void main() async {
// 创建一个服务器实例
final server = LiteEmbeddingsDartServer();
// 启动服务器
await server.start(port: 8080); // 你可以指定端口号
// 添加路由处理
server.addRoute(
path: '/hello',
method: HttpMethod.get,
handler: (HttpRequest request) async {
request.response.write('Hello, World!');
await request.response.close();
},
);
print('Server is running on http://localhost:8080');
}
3. 处理 HTTP 请求
你可以通过 addRoute
方法来添加路由处理逻辑。例如,处理一个简单的 GET
请求:
server.addRoute(
path: '/hello',
method: HttpMethod.get,
handler: (HttpRequest request) async {
request.response.write('Hello, World!');
await request.response.close();
},
);
4. 处理 WebSocket 请求
lite_embeddings_dart_server
还支持 WebSocket 通信。你可以通过以下方式处理 WebSocket 请求:
server.addWebSocketRoute(
path: '/ws',
handler: (WebSocket webSocket) async {
webSocket.listen((message) {
print('Received: $message');
webSocket.add('Echo: $message');
});
},
);
5. 停止服务器
当你不再需要服务器时,可以通过以下方式停止它:
await server.stop();
示例项目
以下是一个完整的示例项目,展示如何在 Flutter 应用中嵌入并使用 lite_embeddings_dart_server
:
import 'package:flutter/material.dart';
import 'package:lite_embeddings_dart_server/lite_embeddings_dart_server.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final server = LiteEmbeddingsDartServer();
await server.start(port: 8080);
server.addRoute(
path: '/hello',
method: HttpMethod.get,
handler: (HttpRequest request) async {
request.response.write('Hello, World!');
await request.response.close();
},
);
server.addWebSocketRoute(
path: '/ws',
handler: (WebSocket webSocket) async {
webSocket.listen((message) {
print('Received: $message');
webSocket.add('Echo: $message');
});
},
);
print('Server is running on http://localhost:8080');
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Lite Embeddings Dart Server')),
body: Center(
child: Text('Server is running on http://localhost:8080'),
),
),
);
}
}