Flutter轻量级嵌入Dart服务器插件lite_embeddings_dart_server的使用

Flutter轻量级嵌入Dart服务器插件lite_embeddings_dart_server的使用

特性

  • 支持向量数据库:Chroma
  • 支持文件类型:纯文本,包括 MarkdownTXT
  • 是Dart List Embeddings的HTTP API封装
  • 基于Lite Embeddings Dart的EmbeddingsService(包含DTO),添加了Controller、Router,并封装为HTTP/WS API。

使用方法

1. 准备工作

  1. 文档文件,根据 /example/docs/*.md
  2. 文件中的分隔符
    • 如果是 markdown 文件,推荐使用 <!--SEPARATOR--> 作为分隔符,以便在渲染后不显示它。
  3. example 文件夹中添加 .env 文件,并在 .env 文件中添加以下内容:
    baseUrl = https://xxx.xxx.com         # LLM API BaseURL
    apiKey = sk-xxxxxxxxxxxxxxxxxxxx      # LLM API ApiKey
    

2. 开发并运行服务器

  1. debugrun 模式下运行 /bin/server.dart 文件的 main() 方法。

3. HTTP API

  • 包含以下API:
3.1 HTTP API
[GET] /version
  • 功能:获取版本号,确认服务是否运行
  • 请求参数:无
  • 响应体示例
    {
        "version": "0.1.0"
    }
    
[POST] /docs/create-by-text
  • 功能:创建文档嵌入,提交整个文本和分隔符,服务将分割并写入向量数据库
  • 请求参数
    • 文档信息:文档名称、文本、分隔符、元数据、LLM 配置
    • 关于元数据:可选,每个段落相同的元数据。默认元数据包括 vdbembeddings_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 配置
    • 关于元数据:可选,默认元数据包括 vdbembeddings_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 配置
    • 关于元数据:可选,默认元数据包括 vdbembeddings_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>:不更新当前元数据
      • {}:清除元数据,但保留默认元数据包括 vdbembeddings_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"
    }
    

构建和运行

  1. 在shell脚本中构建:
    dart compile exe bin/server.dart -o build/lite_embeddings_dart_server
    
  2. 然后,lite_embeddings_dart_server 文件将在 build 文件夹中。
  3. config.json 文件复制到 lite_embeddings_dart_server 的同一文件夹中。
  4. 在shell脚本中运行:
    ./lite_embeddings_dart_server
    
  5. 终端将显示:
    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

1 回复

更多关于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'),
        ),
      ),
    );
  }
}
回到顶部