为 SWIRL 做出贡献的完整指南 🌌 SWIRL

2025-06-07

为 SWIRL 做出贡献的完整指南 🌌

漩涡

你好,开发人员,Swirl
团队创建了这个令人惊叹的指南,其中包含所有相关信息,适合任何想要通过添加 SearchProviders、连接器和处理器来扩展 Swirl 的人。

这让您轻松为 Swirl 做出贡献。立即加入 Swirl,开启开源之旅。我们还将参与 Hacktoberfest 活动,为贡献者提供 Swag 奖品。奖品价值最高可达 100 美元,详情请点击此处的博客查看。

请参阅下面这篇文章,了解有关 Swirl 的更多信息。

在GitHub上给 Swirl 点个赞

漩涡搜索

目录

先决条件

  • 本地安装最新的 Python,3.11 或更高版本
% python
Python 3.11.1 (v3.11.1:a7a450f84a, Dec  6 2022, 15:24:06) [Clang 13.0.0 (clang-1300.0.29.30)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
Enter fullscreen mode Exit fullscreen mode
  • Redis 安装并运行
  • Swirl 安装在本地(不在 Docker 中)并正在运行
% python swirl.py status
__S_W_I_R_L__2_._6__________________________________________________________

Service: redis...RUNNING, pid:31012
Service: django...RUNNING, pid:31014
Service: celery-worker...RUNNING, pid:31018

  PID TTY           TIME CMD
31012 ttys000    0:20.11 redis-server *:6379 
31014 ttys000    0:12.04 /Library/Frameworks/Python.framework/Versions/3.11/Resources/Python.app/Contents/MacOS/Python /Library/Frameworks/Python.framework/Versions/3.11/bin/daphne -b 0.0.0.0 -p 8000 swirl_server.asgi:application
Enter fullscreen mode Exit fullscreen mode

背景:了解 Swirl 搜索工作流程

简而言之:

🕐 每个搜索提供程序并行执行

🕐 结束并行处理

有关更多信息,请参阅开发人员指南工作流概述

创建 SearchProvider

SearchProvider 是 Connector 的配置。因此,要连接到给定源,首先请验证它是否支持您已有的 Connector。(有关如何创建新 Connector 的信息,请参阅下一教程。)

例如,如果尝试使用类似 URL 查询网站https://host.com/?q=my+query+here并返回 JSON 或 XML,请创建一个新的 SearchProvider 并配置 RequestsGet 连接器,如下所示:

  1. 复制任意Google PSE SearchProviders

修改urlquery_template以构造查询 URL。使用上面的示例:

{
        "url": "https://host.com/",
        "query_template": "{url}?q={query_string}",
}
Enter fullscreen mode Exit fullscreen mode

要了解有关查询和 URL 参数的更多信息,请参阅开发人员指南

  1. 如果网站提供分页结果或按日期(以及相关性)对结果进行排序的功能,请使用PAGE=DATE_SORT查询映射通过 Swirl 添加对这些功能的支持。

有关更多信息,请参阅用户指南的查询映射部分:

  1. 在浏览器中打开查询 URL 并查看 JSON 响应。

如果使用 Visual Studio Code,请右键单击粘贴的 JSON 并选择Format Document使其更易于阅读。

  1. 确定结果列表以及找到和检索到的结果数量。将这些 JSON 路径放入响应映射 (response_mappings) 中。然后,确定用于从结果映射 (result_mappings) 中结果列表的每个项目中提取 Swirl 默认字段titlebodyurldate_published的JSON 路径author,其中 Swirl 字段名称位于左侧,源 JSON 路径位于右侧。

例如:


        "response_mappings": "FOUND=searchInformation.totalResults,RETRIEVED=queries.request[0].count,RESULTS=items",
        "result_mappings": "url=link,body=snippet,author=displayLink,cacheId,pagemap.metatags[*].['og:type'],pagemap.metatags[*].['og:site_name'],pagemap.metatags[*].['og:description'],NO_PAYLOAD",
Enter fullscreen mode Exit fullscreen mode
  1. 根据服务要求添加凭证。

使用的格式取决于凭证的类型。详情请参阅:用户指南凭证部分

  1. 添加合适的标签,可用于描述来源或其所知道的内容。

不允许使用空格;好的标签在查询中使用时是清晰明显的,例如company:teslanews:openai

有关标签的更多信息,请参阅:组织 SearchProviders

  1. 回顾一下完成的SearchProvider:

{
        "name": "My New SearchProvider",
        "connector": "RequestsGet",
        "url": "https://host.com/",
        "query_template": "{url}?q={query_string}",
        "query_processors": [
            "AdaptiveQueryProcessor"
        ],
        "query_mappings": "",
        "result_processors": [
            "MappingResultProcessor",
            "CosineRelevancyResultProcessor"
        ],
        "response_mappings": "FOUND=jsonpath.to.number.found,RETRIEVED=jsonpath.to.number.retrieved,RESULTS=jsonpath.to.result.list",
        "result_mappings": "url=link,body=snippet,author=displayLink,NO_PAYLOAD",
        "credentials": "bearer=your-bearer-token-here",
        "tags": [
            "MyTag"
        ]
    }
Enter fullscreen mode Exit fullscreen mode
  1. 前往 Swirl 页面localhost:8000/swirl/searchproviders/,必要时请登录。将页面底部的表单设置为 RAW 模式,并粘贴 SearchProvider 代码。然后点击 POST。SearchProvider 将会重新加载。

  2. 前往 Galaxy localhost:8000/galaxy/,使用之前创建的标签进行搜索。结果应该会在大致相同的时间内再次出现。

创建连接器

在 Swirl 中,连接器负责加载 SearchProvider,然后构建和传输对特定类型服务的查询,然后保存响应 - 通常是结果列表。

:info:考虑使用您最喜欢的编码 AI 来生成连接器,方法是将连接器基类和有关您尝试查询的 API 的信息传递给它。

:info: 如果您尝试向返回 JSON 或 XML 格式的端点发送 HTTP/S 请求,则无需创建连接器。只需创建一个 SearchProvider来配置 Swirl 内置的 RequestsGet 连接器即可。

要创建新的连接器:

  1. 创建一个新文件,例如swirl/connectors/my_connector.py

  2. 复制连接器的样式ChatGPT作为起点,或者BigQuery将其作为数据库的目标。


class MyConnector(Connector):

    def __init__(self, provider_id, search_id, update, request_id=''):
        self.system_guide = MODEL_DEFAULT_SYSTEM_GUIDE
        super().__init__(provider_id, search_id, update, request_id)
Enter fullscreen mode Exit fullscreen mode

init类中,加载并持久化连接和查询服务所需的所有内容。以 ChatGPT 连接器为例。

  1. 导入 Python 包以连接到服务。ChatGPT 连接器使用 openai 包,例如:
import openai
Enter fullscreen mode Exit fullscreen mode
  1. 修改execute_search方法以连接到服务。

从 ChatGPT 连接器中可以看到,它首先加载 OpenAI 凭证,然后构建提示,通过发送提示openai.ChatCompletion.create(),然后存储响应。


    def execute_search(self, session=None):

        logger.debug(f"{self}: execute_search()")

        if self.provider.credentials:
            openai.api_key = self.provider.credentials
        else:
            if getattr(settings, 'OPENAI_API_KEY', None):
                openai.api_key = settings.OPENAI_API_KEY
            else:
                self.status = "ERR_NO_CREDENTIALS"
                return

        prompted_query = ""
        if self.query_to_provider.endswith('?'):
            prompted_query = self.query_to_provider
        else:
            if 'PROMPT' in self.query_mappings:
                prompted_query = self.query_mappings['PROMPT'].format(query_to_provider=self.query_to_provider)
            else:
                prompted_query = self.query_to_provider
                self.warning(f'PROMPT not found in query_mappings!')

        if 'CHAT_QUERY_REWRITE_GUIDE' in self.query_mappings:
            self.system_guide = self.query_mappings['CHAT_QUERY_REWRITE_GUIDE'].format(query_to_provider=self.query_to_provider)

        if not prompted_query:
            self.found = 0
            self.retrieved = 0
            self.response = []
            self.status = "ERR_PROMPT_FAILED"
            return
        logger.info(f'CGPT completion system guide:{self.system_guide} query to provider : {self.query_to_provider}')
        self.query_to_provider = prompted_query
        completions = openai.ChatCompletion.create(
            model=MODEL,
            messages=[
                {"role": "system", "content": self.system_guide},
                {"role": "user", "content": self.query_to_provider},
            ],
            temperature=0,
        )
        message = completions['choices'][0]['message']['content'] # FROM API Doc

        self.found = 1
        self.retrieved = 1
        self.response = message.replace("\n\n", "")

        return
Enter fullscreen mode Exit fullscreen mode

ChatGPT 依赖于 OpenAI API 密钥,该密钥通过 .env 文件提供给 Swirl。要遵循此模式,请在 .env 中创建新值,然后修改swirl_server/settings.py以将其加载为 Django 设置,并设置合理的默认值。

  1. 修改该normalize_response()方法以存储原始响应。实际上,这只不过是将结果对象写成 Python 列表并将其存储在self.results

    def normalize_response(self):

        logger.debug(f"{self}: normalize_response()")

        self.results = [
                {
                'title': self.query_string_to_provider,
                'body': f'{self.response}',
                'author': 'CHATGPT',
                'date_published': str(datetime.now())
            }
        ]

        return
Enter fullscreen mode Exit fullscreen mode

如果 self.response 已经是一个 python 列表,则无需执行此操作。

  1. 将新连接器添加到swirl/connectors/__init__.py
from swirl.connectors.my_connector import MyConnector
Enter fullscreen mode Exit fullscreen mode
  1. 重启 Swirl
% python swirl.py restart core
Enter fullscreen mode Exit fullscreen mode
  1. 创建一个 SearchProvider 来配置新的连接器,然后按照创建 SearchProvider 教程中的说明将其添加到 Swirl 安装中

不要忘记有用的标签,以便您在准备测试时可以轻松定位新的连接器。

要了解有关开发连接器的更多信息,请参阅开发人员指南

创建查询处理器

QueryProcessor 是在预查询或查询处理过程中执行的一个阶段。两者的区别在于,预查询处理应用于所有 SearchProvider,而查询处理由每个 SearchProvider 单独执行。在这两种情况下,目标都是修改发送给部分或全部 SearchProvider 的查询。

注意:如果您只想使用查找表或正则表达式重写查询,请考虑使用QueryTransformations

要创建新的 QueryProcessor:

  1. 创建一个新文件,例如swirl/processors/my_query_processor.py

  2. 复制GenericQueryProcessor该类作为起点,然后重命名:


class MyQueryProcessor(QueryProcessor):

    type = 'MyQueryProcessor'

    def process(self):
        # TO DO: modify self.query_string, and return it 
        return self.query_string + ' modified'
Enter fullscreen mode Exit fullscreen mode

保存模块。

  1. 将新模块添加到swirl/processors/__init__.py

from swirl.processors.my_processor import MyQueryProcessor
Enter fullscreen mode Exit fullscreen mode
  1. 将新模块添加到 Search.pre_query_processing 管道或至少一个 SearchProvider.query_processing 管道:

SearchProvider


        "query_processors": [
            "AdaptiveQueryProcessor",
            "MyQueryProcessor"
        ],
Enter fullscreen mode Exit fullscreen mode

Search


  {
        "query_string": "news:ai",
        "pre_query_processors": [
          "MyQueryProcessor"
        ],
  }
Enter fullscreen mode Exit fullscreen mode
  1. 重启 Swirl
% python swirl.py restart core
Enter fullscreen mode Exit fullscreen mode
  1. 前往 Galaxyhttp://localhost:8000/swirl/search/?q=some+query

运行搜索;如果使用查询处理器,请务必指定相应的 SearchProvider。例如,如果您将 QueryProcessor 添加到带有标签“news”的 SearchProvider query_processing 管道,则查询将http://localhost:8000/swirl/search/?q=news:some+query改为:

结果应该在几秒钟内出现。在messages代码块中应该会出现一条消息,表明新的 QueryProcessor 重写了查询:

MyQueryProcessor rewrote Strategy Consulting - Google PSE's query to: <modified-query> 
Enter fullscreen mode Exit fullscreen mode

要了解有关编写处理器的更多信息,请参阅开发人员指南

创建 ResultProcessor

ResultProcessor 是每个 SearchProvider 在 Connector 检索到结果后执行的一个阶段。ResultProcessor 对结果进行操作,并根据需要对其进行转换,以供下游使用或呈现。

GenericResultProcessor 和 MappingResultProcessor 阶段旨在规范化 JSON 结果。GenericResultProcessor 搜索与 Swirl 模式完全匹配的结果(如 SearchProvider 示例中所示),并将其复制过来。MappingResultProcessor 应用 result_mappings 来规范化结果,同样如上文 SearchProvider 示例中所示。通常,在这些阶段之后添加阶段是个好主意,除非 SearchProvider 需要以 Swirl 模式格式响应。

要创建新的 ResultProcessor:

  1. 创建一个新文件,例如swirl/processors/my_result_processor.py

  2. 复制GenericResultProcessor该类作为起点,然后重命名。不要忘记init

class MyResultProcessor(ResultProcessor):

    def __init__(self, results, provider, query_string, request_id='', **kwargs):
        super().__init__(results, provider, query_string, request_id=request_id, **kwargs)
Enter fullscreen mode Exit fullscreen mode
  1. 实现该process()方法。这是唯一需要的。

Process() 操作于self.results,它将以 Python 列表格式包含来自给定 SearchProvider 的所有结果。修改结果列表中的项目,并报告更新的数量。

    def process(self):

        if not self.results:
            return

        updated = 0
        for item in self.results:
            # TO DO: operate on each item and count number updated
            item['my_field1'] = 'test'
            updated = updated + 1

        # note: there is no need to save in this type of Processor

        # save modified self.results
        self.processed_results = self.results
        # save number of updated
        self.modified = updated

        return self.modified
Enter fullscreen mode Exit fullscreen mode

保存模块。

  1. 将新模块添加到swirl/processors/__init__.py
from swirl.processors.my_processor import MyResultProcessor
Enter fullscreen mode Exit fullscreen mode
  1. 将新模块添加到至少一个 SearchProvider.result_processing 管道:
        "result_processors": [
            "MappingResultProcessor",
            "MyResultProcessor",
            "CosineRelevancyResultProcessor"
        ],
         ...etc...
Enter fullscreen mode Exit fullscreen mode
  1. 重启 Swirl
% python swirl.py restart core
Enter fullscreen mode Exit fullscreen mode
  1. 前往 Galaxyhttp://localhost:8000/swirl/search/?q=some+query

运行搜索;确保至少定位一个具有新 ResultProcessor 的 SearchProvider。

例如,如果您将 ResultProcessor 添加到带有标签“news”的 SearchProvider result_processing 管道,则查询将需要http://localhost:8000/swirl/search/?q=news:some+query代替上述内容。

结果应该在几秒钟内出现。在messages代码块中应该出现一条消息,表明新的 ResultProcessor 更新了多个结果,并且内容应该按预期进行修改。

MyResultProcessor updated 5 results from: MyConnector",
Enter fullscreen mode Exit fullscreen mode

要了解有关编写处理器的更多信息,请参阅开发人员指南

创建 PostResultProcessor

PostResultProcessor 是所有 SearchProvider 返回结果后执行的一个阶段。它们会对给定查询的所有结果进行操作。

要创建新的 ResultProcessor:

  1. 创建一个新文件,例如swirl/processors/my_post_result_processor.py

  2. 复制下面的模板作为起点,然后重命名:

class MyPostResultProcessor(PostResultProcessor):

    type = 'MyPostResultProcessor'

    ############################################

    def __init__(self, search_id, request_id = ''):
        return super().__init__(search_id, request_id=request_id)

    ############################################

    def process(self):

        updated = 0

        for results in self.results:
            if not results.json_results:
                continue
            for item in results.json_results:
                # TO DO: operate on each result item
                item['my_field2'] = "test"
                updated = updated + 1
            # end for
            # call results.save() if any results were modified
            if updated > 0:
                results.save()

        # end for
        ############################################

        self.results_updated = updated
        return self.results_updated
Enter fullscreen mode Exit fullscreen mode

修改process()方法,对项目进行操作并保存每个结果集,如下所示。

  1. 将新模块添加到swirl/processors/__init__.py
from swirl.processors.my_post_result_processor import MyPostResultProcessor
Enter fullscreen mode Exit fullscreen mode
  1. 将新模块添加到 Search.post_result_processing 管道:
  {
        "query_string": "news:ai",
        "post_result_processors": [
            "DedupeByFieldPostResultProcessor",
            "CosineRelevancyPostResultProcessor",
            "MyPostResultProcessor"
        ],
        ...etc...
    }
Enter fullscreen mode Exit fullscreen mode
  1. 重启 Swirl
% python swirl.py restart core
Enter fullscreen mode Exit fullscreen mode
  1. 前往 Galaxyhttp://localhost:8000/swirl/search/?q=some+query

运行搜索;确保至少定位一个具有新 PostResultProcessor 的 SearchProvider。

例如,如果您向post_result_processing带有标签“news”的搜索管道添加了 PostResultProcessor,则查询将需要http://localhost:8000/swirl/search/?q=news:some+query代替上述内容。

结果应该在几秒钟内出现。在messages代码块中应该出现一条消息,表明新的 PostResultProcessor 更新了多个结果,并且内容应该按预期进行修改。

MyPostResultProcessor updated 10 results from: MySearchProvider
Enter fullscreen mode Exit fullscreen mode

要了解有关编写处理器的更多信息,请参阅开发人员指南

加入社区

在 GitHub 上给 Swirl 点个赞。

GitHub 徽标 swirlai /漩涡搜索

无需移动数据,即可进行 AI 搜索和 RAG 操作。从公司 100 多个应用的​​知识库中获取即时答案,同时确保数据安全。部署只需几分钟,无需数月。

漩涡

漩涡

无需将数据移动到云端,即可为您的团队提供 ChatGPT 级搜索

60 秒内将 RAG 与 One Drive 和 Microsoft 365 结合使用

提出问题 → 获取答案和来源 → 点击查看来源

SWIRL One Drive RAG

在YouTube上观看

使用 SWIRL 的团队每周平均可节省 7.5 小时的生产时间。

将人工智能引入数据通讯

🤔 为什么选择 SWIRL?

避开复杂性,保持强大功能








❌ 无 SWIRL

  • 设置矢量数据库
  • 移动数据
  • 复杂的 ETL 管道
  • 数周的基础设施工作
  • 安全难题

✅ 使用 SWIRL

  • 一个docker命令
  • 数据保留在原处
  • 无需向量数据库
  • 2分钟设置
  • 企业级安全

🚀 与众不同

无向量 DB 戏剧

# No need for:
$ setup-vector-db
$ migrate-data
$ configure-indexes

# Just this:
$ curl https://raw.githubusercontent.com/swirlai/swirl-search/main/docker-compose.yaml -o docker-compose.yaml
Enter fullscreen mode Exit fullscreen mode

💡 您可以用 SWIRL 构建什么?

团队的真实例子……




文章来源:https://dev.to/swirl/your-full-guide-to-contributing-to-swirl-256f
PREV
瑞士比硅谷更适合软件开发者的 8 个理由
NEXT
2025 年商业和初创企业最佳 AI 搜索引擎