├── site ├── configs │ ├── config.md │ ├── credentials.md │ └── endpoint.md ├── api │ ├── aiops │ │ ├── anomaly │ │ │ ├── img │ │ │ │ ├── KNN.excalidraw │ │ │ │ ├── KNN.png │ │ │ │ ├── MAD.png │ │ │ │ ├── SOS.png │ │ │ │ ├── ABOD.png │ │ │ │ ├── ECOD.png │ │ │ │ ├── Help.png │ │ │ │ ├── INNE.png │ │ │ │ ├── KPCA.png │ │ │ │ ├── OCSVM.png │ │ │ │ ├── SUOD.png │ │ │ │ ├── XGBOD.png │ │ │ │ ├── IForest.png │ │ │ │ ├── KPCA.excalidraw │ │ │ │ ├── OCSVM.excalidraw │ │ │ │ └── MAD.excalidraw │ │ │ ├── mad.md │ │ │ ├── abod.md │ │ │ ├── knn.md │ │ │ ├── oneclasssvm.md │ │ │ ├── suod.md │ │ │ ├── ecod.md │ │ │ ├── inne.md │ │ │ ├── iforest.md │ │ │ ├── kpca.md │ │ │ └── xgbod.md │ │ ├── logreduce │ │ │ ├── img │ │ │ │ ├── drain3.png │ │ │ │ ├── spell.png │ │ │ │ ├── drain3_example.png │ │ │ │ └── spell_example.png │ │ │ └── drain3.md │ │ ├── timeseries │ │ │ ├── img │ │ │ │ ├── Holt.png │ │ │ │ ├── LSTM.png │ │ │ │ └── Prophet.png │ │ │ ├── holtwinter.md │ │ │ └── sarima.md │ │ └── causation │ │ │ ├── fpgrowth.md │ │ │ └── causality.md │ ├── classicfy_aiops_server.md │ ├── fast_embed_server.md │ ├── bce_embed_server.md │ ├── ocr_server.md │ ├── pandoc_server.md │ ├── saltstack_server.md │ ├── bionics.md │ ├── chat_server.md │ ├── chunk_server.md │ └── rag_server.md ├── channel │ ├── index.md │ ├── dingtalk.md │ ├── enterprise-wechat.md │ └── web.md ├── skills │ ├── automation.md │ ├── itsm.md │ ├── index.md │ ├── security.md │ ├── devops.md │ └── common.md ├── Dockerfile ├── package.json ├── development.md ├── features │ ├── contentpack.md │ ├── channels.md │ ├── system.md │ ├── bot.md │ ├── knowledges.md │ └── ai_models.md ├── architecture.md ├── models.md ├── version.md ├── quick-start.md ├── index.md ├── introduction.md └── .vitepress │ └── config.mts ├── support-files ├── images │ ├── wx.jpg │ ├── main.jpg │ └── chatbot.png └── docker │ └── Dockerfile.base ├── Makefile ├── .gitignore ├── Readme.md ├── .gitmodules ├── Readme-cn.md └── LICENSE /site/configs/config.md: -------------------------------------------------------------------------------- 1 | # 模型训练配置 2 | -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/KNN.excalidraw: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/channel/index.md: -------------------------------------------------------------------------------- 1 | # 通道概览 2 | 3 | OpsPilot支持多种消息通道,包括: 4 | 5 | * Web 6 | * 企业微信 -------------------------------------------------------------------------------- /support-files/images/wx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/support-files/images/wx.jpg -------------------------------------------------------------------------------- /support-files/images/main.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/support-files/images/main.jpg -------------------------------------------------------------------------------- /support-files/images/chatbot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/support-files/images/chatbot.png -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/KNN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/anomaly/img/KNN.png -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/MAD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/anomaly/img/MAD.png -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/SOS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/anomaly/img/SOS.png -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/ABOD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/anomaly/img/ABOD.png -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/ECOD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/anomaly/img/ECOD.png -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/Help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/anomaly/img/Help.png -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/INNE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/anomaly/img/INNE.png -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/KPCA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/anomaly/img/KPCA.png -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/OCSVM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/anomaly/img/OCSVM.png -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/SUOD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/anomaly/img/SUOD.png -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/XGBOD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/anomaly/img/XGBOD.png -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/IForest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/anomaly/img/IForest.png -------------------------------------------------------------------------------- /site/api/aiops/logreduce/img/drain3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/logreduce/img/drain3.png -------------------------------------------------------------------------------- /site/api/aiops/logreduce/img/spell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/logreduce/img/spell.png -------------------------------------------------------------------------------- /site/api/aiops/timeseries/img/Holt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/timeseries/img/Holt.png -------------------------------------------------------------------------------- /site/api/aiops/timeseries/img/LSTM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/timeseries/img/LSTM.png -------------------------------------------------------------------------------- /site/api/aiops/timeseries/img/Prophet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/timeseries/img/Prophet.png -------------------------------------------------------------------------------- /site/api/aiops/logreduce/img/drain3_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/logreduce/img/drain3_example.png -------------------------------------------------------------------------------- /site/api/aiops/logreduce/img/spell_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WeOps-Lab/OpsPilot/HEAD/site/api/aiops/logreduce/img/spell_example.png -------------------------------------------------------------------------------- /site/skills/automation.md: -------------------------------------------------------------------------------- 1 | # 自动化 2 | 3 | ## 自动化运维 4 | 5 | OpsPilot支持与SaltStack集成,完成ChatOps下的自动化运维能力。 6 | 7 | ![自动化](https://static.cwoa.net/a1ca7699f4c246b4bcad902807012d01.gif) -------------------------------------------------------------------------------- /site/channel/dingtalk.md: -------------------------------------------------------------------------------- 1 | # 钉钉 2 | 3 | ## 配置 4 | 5 | ``` 6 | channels.dingtalk_channel.dingtalk_channel.DingTalkChannel: 7 | client_id: "" 8 | client_secret: "" 9 | ``` 10 | -------------------------------------------------------------------------------- /site/skills/itsm.md: -------------------------------------------------------------------------------- 1 | ## 智能工单 2 | 3 | ### 智能提单引导 4 | 用户以Web或者IM的通道可以对OpsPilot进行知识问答,在问答的过程中,用户可以提出提单的要求 5 | 6 | ![智能提单.gif](https://static.cwoa.net/3eaa646cf431429383f79a44513fe324.gif) -------------------------------------------------------------------------------- /site/skills/index.md: -------------------------------------------------------------------------------- 1 | # 能力概览 2 | 3 | OpsPilot支持包括`日常`、`安全`、`DevOps`、`智能工单`、`自动化`等多个领域的技能,通过将ChatOps与LLMOps的能力进行联动,提供智能运维助理的能力。 4 | 5 | ![能力概览.png](https://static.cwoa.net/1b20d040bb0b4974adb9b7b68c5ef573.png) -------------------------------------------------------------------------------- /site/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18.19.0 as build-stage 2 | WORKDIR /app 3 | COPY . . 4 | RUN yarn && yarn run docs:build 5 | 6 | FROM nginx 7 | COPY --from=build-stage /app/.vitepress/dist /usr/share/nginx/html 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | push: 2 | git add . && codegpt commit . && git push 3 | 4 | update-submodules: 5 | git pull --recurse-submodules 6 | git submodule update --init --recursive 7 | git submodule update --remote --merge 8 | -------------------------------------------------------------------------------- /site/skills/security.md: -------------------------------------------------------------------------------- 1 | # 安全 2 | 3 | OpsPilot提供了安全运维领域的自动化能力 4 | 5 | ## 资产测绘 6 | 7 | OpsPilot可以使用资产测绘能力,对目标对象的端口、域名等信息进行测绘,以便于后续的安全检测 8 | 9 | ![资产测绘.gif](https://static.cwoa.net/9f5f461336844dbe8e849a5a40c2c572.gif) -------------------------------------------------------------------------------- /site/skills/devops.md: -------------------------------------------------------------------------------- 1 | # DevOps 2 | 3 | ## 构建分析 4 | 5 | OpsPilot支持WebHook,当Jenkins触发构建失败的时候,可以将构建失败的信息发送到OpsPilot中,OpsPilot会将构建失败原因进行分析,通知用户此次 6 | 构建失败的可能原因以及修复建议。 7 | 8 | ## Gitlab代码Review 9 | 10 | 支持对用户提交到Gitlab的代码进行自动Review -------------------------------------------------------------------------------- /site/api/classicfy_aiops_server.md: -------------------------------------------------------------------------------- 1 | classicfy-aiops-server contains the classic AIOPS algorithm. It is a stateless service that provides classic AIOPS algorithm capabilities including anormaly detection, time series prediction, and log clustering etc... 2 | -------------------------------------------------------------------------------- /site/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "docs:dev": "vitepress dev", 4 | "docs:build": "vitepress build", 5 | "docs:preview": "vitepress preview" 6 | }, 7 | "devDependencies": { 8 | "vitepress": "^1.1.4" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /site/configs/credentials.md: -------------------------------------------------------------------------------- 1 | # Credentials配置 2 | 3 | Credentials主要配置OpsPilot的各种Channel,以及Channel对应的凭证信息 4 | 5 | ## Socketio 6 | 7 | ## Rest 8 | 9 | ## 企业微信应用 10 | 11 | ## 企业微信机器人 12 | 13 | ## 钉钉机器人 14 | 15 | ## Slack 16 | 17 | ## Gitlab Code Review -------------------------------------------------------------------------------- /support-files/docker/Dockerfile.base: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y libhdf5-dev vim python3 python3-pip unzip curl pkg-config libssl-dev libffi-dev supervisor && \ 5 | apt-get clean && \ 6 | rm -rf /var/lib/apt/lists/* 7 | -------------------------------------------------------------------------------- /site/api/fast_embed_server.md: -------------------------------------------------------------------------------- 1 | Fast Embed Server hosts the Fast Embed model and can generate embed relatively quickly on the CPU 2 | 3 | ## Embedding 4 | 5 | ### LangServer API 6 | 7 | ```python 8 | remote = RemoteRunnable(f'{fast_embed_server}') 9 | embed=remote.invoke("content") 10 | ``` 11 | -------------------------------------------------------------------------------- /site/skills/common.md: -------------------------------------------------------------------------------- 1 | # 日常 2 | 3 | ## 知识问答 4 | 知识问答主要用于帮助用户使用OpsPilot做私域知识的问答 5 | ![知识问答.png](https://static.cwoa.net/42aff4f013bd44b4aa215b24720bfa78.png) 6 | 7 | ## 对话总结 8 | 对话总结可以帮助用户在多轮对话后,对内容进行总结,后续可以进行知识转移、邮件发送等操作 9 | ![聊天总结.png](https://static.cwoa.net/8f5ec66acfa24661ae968139ebe55e67.png) 10 | 11 | ## OCR识别 12 | OpsPilot支持用户在企业微信中上传图片,进行OCR识别,识别结果可以直接返回给用户 -------------------------------------------------------------------------------- /site/development.md: -------------------------------------------------------------------------------- 1 | # 本地开发 2 | 3 | 4 | ## 前置依赖 5 | 6 | ``` 7 | pip install pip-tools 8 | ``` 9 | 10 | ## 准备虚拟环境 11 | 12 | ``` 13 | virtualenv .venv -p python3.10 14 | ``` 15 | 16 | ## 安装依赖 17 | 18 | ``` 19 | make venv-install 20 | ``` 21 | 22 | ## 训练模型 23 | ``` 24 | make train 25 | ``` 26 | 27 | ## 启动服务 28 | ``` 29 | make run 30 | make actions 31 | make celery 32 | ``` -------------------------------------------------------------------------------- /site/api/bce_embed_server.md: -------------------------------------------------------------------------------- 1 | The BCE Embed service provides both ReRank and Embed capabilities and is suitable for running on servers with gpu 2 | 3 | ## Embedding 4 | 5 | ```python 6 | remote = RemoteRunnable(f'{embed_server}/embed') 7 | embed=remote.invoke("content") 8 | ``` 9 | 10 | ## ReRanking 11 | 12 | ```python 13 | remote = RemoteRunnable(f'{embed_server}/rerank') 14 | rerank_result=remote.invoke({ 15 | "docs": [], 16 | "query": "", 17 | "top_n": 10 18 | }) 19 | ``` 20 | -------------------------------------------------------------------------------- /site/features/contentpack.md: -------------------------------------------------------------------------------- 1 | # 扩展包 2 | 3 | 模型扩展包对应的是Rasa的模型,Pilot的基础是Rasa,所以扩展包模块是用来更好的管理Rasa的训练语料,扩展包的功能与Rasa的语料包功能一一对应。 4 | 5 | 模型是Pilot的核心。在运维操作中,我们会更希望任务的执行具备以更低的调优成本让运维动作具备更高确定性,使用LLM Agent+Function Call,并不能够低成本的获得这个特性,所以OpsPilot结合了任务型机器人与开放领域对话型机器人的特点,让Pilot具备ChatOps与智能引导的核心能力。 6 | 7 | 8 | ## ChatOps 9 | 10 | 在Rasa框架的帮助下,我们可以为Pilot编写ChatOps的语料包,完整运维数据的收集、运维动作的执行 11 | 12 | 13 | ## 智能引导 14 | 15 | 借助Rasa的确定性对话流+预测性对话流的能力,可以将用户的对话从开放领域引导至Pilot的对话流,在对话流中,Pilot具备任务执行与信息收集的能力,并通过消息进行返回。返回的消息可以被作为大语言模型的对话上下文,由大语言模型进一步的进行对话总结、推荐等能力。完成复杂的智能引导任务 16 | -------------------------------------------------------------------------------- /site/channel/enterprise-wechat.md: -------------------------------------------------------------------------------- 1 | # 企业微信 2 | 3 | ## 企业微信应用 4 | 5 | 要开启OpsPilot企业应用集成,需要在`creadentials.yml`中配置企业微信应用的相关信息。 6 | 7 | ```yaml 8 | channels.enterprise_wechat.enterprise_wechat_channel.EnterpriseWechatChannel: 9 | corp_id: "" 10 | secret: "" 11 | token: "" 12 | aes_key: "" 13 | agent_id: "" 14 | ``` 15 | 16 | 在企业微信中找到上述配置,填入即可 17 | 18 | ## 企业微信Jenkins构建分析机器人 19 | 20 | ```yaml 21 | channels.jenkins_notifycation.enterprise_wechat_jenkins_notification.EnterpriseWeChatJenkinsNotification: 22 | fastgpt_url: 23 | fastgpt_token: 24 | enterprise_bot_url: 25 | secret_token: 26 | ``` 27 | -------------------------------------------------------------------------------- /site/api/ocr_server.md: -------------------------------------------------------------------------------- 1 | OCR Server service provides the ability to extract text from images 2 | 3 | ## Paddle OCR 4 | ``` 5 | ocr_remote = RemoteRunnable(f'{ocr_server}/paddle_ocr') 6 | with open(image_path, "rb") as file: 7 | content = file_remote.invoke({ 8 | "file": base64.b64encode(file.read()).decode('utf-8'), 9 | }) 10 | ``` 11 | 12 | ## Azure OCR 13 | 14 | ``` 15 | ocr_remote = RemoteRunnable(f'{ocr_server}/azure_ocr') 16 | with open(image_path, "rb") as file: 17 | content = file_remote.invoke({ 18 | "file": base64.b64encode(file.read()).decode('utf-8'), 19 | }) 20 | ``` -------------------------------------------------------------------------------- /site/api/pandoc_server.md: -------------------------------------------------------------------------------- 1 | The pandoc server provides the document format conversion service 2 | 3 | ## Convert document format 4 | 5 | ```python 6 | import requests 7 | 8 | content="" #base64 encoded content 9 | pure_filename="" #filename without extension 10 | file_type="" #file extension 11 | 12 | with tempfile.NamedTemporaryFile(delete=False) as f: 13 | response = requests.post( 14 | f'{pandoc_server_host}/convert', 15 | data={'output': 'docx'}, 16 | files={'file': (pure_filename + file_type, content)} 17 | ) 18 | response.raise_for_status() 19 | f.write(response.content) 20 | ``` 21 | 22 | or use the following curl command 23 | 24 | ```bash 25 | curl -X POST "http://your-pandoc-server/convert" \ 26 | -F "output=pdf" \ 27 | -F "file=@example.md" \ 28 | --output converted.pdf 29 | ``` -------------------------------------------------------------------------------- /site/architecture.md: -------------------------------------------------------------------------------- 1 | # 架构概览 2 | 3 | ## 核心概念 4 | 5 | 在OpsPilot里面,有以下核心概念: 6 | 7 | * **机器人**:每个机器人就是一个Pilot。Pilot被K8S调度,通过通道与用户接触 8 | * **AI模型**:AI模型为Pilot提供了AI技能,可以简单的认为扩展包告诉了Pilot能做哪些动作,AI模型为动作提供了魔法😁。AI模型也可以直接对外提供服务 9 | * **集成**:集成是Pilot与外部系统联动的方式,包括K8S、Jenkins、Gitlab、WeOps Lite等 10 | * **通道**:通道是Pilot与用户连接的渠道,包括钉钉、Web、企业微信 11 | * **知识库**:知识库为机器人提供了RAG的支撑,使得机器人可以回复私域知识 12 | 13 | ## 显性知识&隐性知识 14 | * **显性知识**: 我们认为在运维系统里面,一切直接表达出来的,例如CMDB的资产关联关系、告警信息、指标信息等等,都是显性知识 15 | * **隐性知识**:我们认为在运维系统里面,一切需要通过推理、计算、预测等方式得到的,例如根因分析、预测性告警等等,通过AIOPS算法对显性知识提炼分析的,统一称之为隐性知识 16 | 17 | ## 智能引导 18 | OpsPilot暂时还没有把自己定位为Virtual SRE,我们认为现阶段,让大模型在运维领域发挥过多的主观能动性的可靠程度是不高的。所以我们更倾向于结合任务型机器人和对话型机器人的优势,引导用户一步一步的完成运维任务,或者分析出告警的根因 19 | 20 | 21 | ## 系统架构 22 | 23 | OpsPilot由基础设施、AI Service以及业务层组成 24 | 25 | ![arch-2.4.png](https://static.cwoa.net/d66af16085b043979ca7e20c0c05e2b0.png) 26 | -------------------------------------------------------------------------------- /site/features/channels.md: -------------------------------------------------------------------------------- 1 | # 通道管理 2 | 3 | 通道是Pilot与用户接触的管道,OpsPilot提供了多种方式让用户与Pilot之间能够交互 4 | 5 | ## 消息通道 6 | 7 | OpsPilot内置了多种消息通道,让Pilot能够与用户进行交流,支持的消息通道包含: 8 | 9 | * Web:可以通过嵌入WebChat组件,在网页中与Pilot进行交流 10 | * 企业微信应用 11 | * 企业微信群机器人 12 | * 钉钉 13 | * Gitlab 14 | 15 | ![通道1.png](https://static.cwoa.net/90df83025a1342d9953a5a8811469993.png) 16 | 17 | 消息通道的配置,需要选择类型填写配置参数(比如企业微信,需要填写AES密钥、企微应用的agentID、企微的企业ID、企微应用的Secret密钥和用于验证消息有效性的token) 18 | 19 | ![通道2.png](https://static.cwoa.net/9721c6a08fa74c69a9fb1df40bcbc99f.png) 20 | 21 | 消息通道创建完成后,可以被机器人所使用,成为和用户交互的门户。 22 | 23 | ## 用户组 24 | 25 | 用户组属于消息通道,用于区分与Pilot进行交流的用户,属于通道的哪个用户组,目前内置的5类消息通道各有一个默认用户组。 26 | 27 | ![用户1.png](https://static.cwoa.net/49254da719794b009f58c7e3f9c95f07.png) 28 | 29 | 30 | ## 用户 31 | 32 | 记录了与Pilot进行交流的用户,当用户与Pilot进行了交流后,会自动创建用户记录,在人工介入的环节,我们就可以与用户发起主动聊天 33 | 34 | ![用户2.png](https://static.cwoa.net/0b7c841120984bab915673be3a61463f.png) -------------------------------------------------------------------------------- /site/channel/web.md: -------------------------------------------------------------------------------- 1 | # Web 2 | 3 | ## WebSocket&Rest 4 | 5 | OpsPilot默认开启了5005端口,提供Web端集成,集成的时候,在前端界面加入以下代码,就可以继承了 6 | 7 | ``` 8 | 29 | ``` -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | .venv 3 | .idea 4 | .vscode 5 | requirements.txt 6 | .env 7 | cache 8 | 9 | .pytest_cache 10 | 11 | pilot/models/* 12 | pilot/tracker.db 13 | pilot/tensorboard 14 | __pycache__ 15 | pilot/endpoints-prod.yml 16 | pilot/.rasa 17 | pilot/credentials-prod.yml 18 | *.zip 19 | !munchkin/support-files/data/* 20 | 21 | pilot/graph.html 22 | 23 | munchkin/templates/* 24 | munchkin/assets 25 | munchkin/db.sqlite3 26 | munchkin/nltk_data 27 | site/node_modules 28 | site/pnpm-lock.yaml 29 | 30 | model_server/bce_rerank_server/models 31 | model_server/bce_embed_server/models 32 | model_server/fast_embed_server/models 33 | model_server/chunk_server/models 34 | model_server/chunk_server/tests/asserts/*.pdf 35 | model_server/chunk_server/tests/asserts/*.xlsx 36 | model_server/chunk_server/tests/asserts/*.docx 37 | model_server/chunk_server/tests/asserts/*.pptx 38 | 39 | pilot/story_graph.dot 40 | model_server/ocr_server/models 41 | model_server/ocr_server/tests/asserts/ 42 | site/.vitepress/dist -------------------------------------------------------------------------------- /site/models.md: -------------------------------------------------------------------------------- 1 | # 模型下载 2 | 3 | ## Pilot 4 | 5 | > 需要解压到 `./cache/models/`目录下 6 | 7 | * [Bert-Base-Chinese](https://pan.baidu.com/s/1m28lvGOXeTQpjtZwCSJyTQ?pwd=fprq) 8 | 9 | ## BCE Embed Server 10 | 11 | > 需要解压到 `bce_embed_server/models`目录下 12 | 13 | * [BCEEmbed-Base-V1](https://pan.baidu.com/s/1xNfgm8Xf-zPCr9UhEK04dQ?pwd=9mjs) 14 | 15 | ## BCE ReRank Server 16 | 17 | > 需要解压到 `bce_rerank_server/models`目录下 18 | 19 | * [BCE-ReRanker-Base-V1](https://pan.baidu.com/s/1-iZ8yij_Z-bccSuWDjewBQ?pwd=npek) 20 | 21 | ## Fast Embed Server 22 | 23 | > 需要解压到 `fast_embed_server/models`目录下 24 | 25 | * [Fast-BGE-Small-zh-v1.5](https://pan.baidu.com/s/1F0MwIy_Be5gYgxOwEcEHgQ?pwd=67ar) 26 | * [Fast-BGE-Small-en-v1.5](https://pan.baidu.com/s/1YiWB1FPnqsdUcp55xUJQag?pwd=jrz1) 27 | 28 | ## Chunk Server 29 | 30 | > 需要解压到 `chunk_server/models`目录下 31 | 32 | * [NLTK](https://pan.baidu.com/s/1R4So_oSdAbhepjYXCZhccw?pwd=yjqz) 33 | 34 | ## OCR Server 35 | > 需要解压到 `ocr_server/models`目录下 36 | * [PaddleOCR](https://pan.baidu.com/s/1M8KfK84RhCPvChW1mTDARg?pwd=s4mr) 37 | -------------------------------------------------------------------------------- /site/api/aiops/anomaly/mad.md: -------------------------------------------------------------------------------- 1 | # MAD 2 | 3 | ## Algorithm Introduction 4 | 5 | Median Absolute Deviation (MAD) is a comprehensive method for detecting outliers by calculating the distance between each observation and the mean. 6 | 7 | ## Usage scenarios 8 | 9 | This algorithm is suitable for outlier detection on single-index numerical data. 10 | 11 | ## Algorithm principle 12 | 13 | ![Excalidraw Image](./img/MAD.png) 14 | 15 | As shown in the figure above, first find the median MA of indicator A, then subtract MA from all the values ​​of indicator A to get the value of variable B. Find the absolute value of B and then find its median MC, and MC performs MAD correction to obtain MAD. The normal range is determined based on MAD and MA. Values ​​outside this range will be identified as abnormal values. 16 | 17 | * Link to the original paper: https://books.google.com/books?hl=zh-CN&lr=&id=FuuiEAAAQBAJ&oi=fnd&pg=PP1&dq=Iglewicz,+B.+and+Hoaglin,+D.C.,+1993.+How+to+detect+and+handle+outliers+(Vol.+16).+Asq+Press.&ots=SEU5R3XTQn&sig=3bGO1vTuZpQfPE8QIfX7QGyjTq8#v=onepage&q=Iglewicz%2C%20B.%20and%20Hoaglin%2C%20D.C.%2C%201993.%20How%20to%20detect%20and%20handle%20outliers%20(Vol.%2016).%20Asq%20Press.&f=false -------------------------------------------------------------------------------- /site/features/system.md: -------------------------------------------------------------------------------- 1 | # 系统管理 2 | 3 | 4 | ## 用户管理 5 | 6 | 系统管理中的用户和用户组是用于管理系统访问和权限的组织和授权工具。以下是对用户和用户组的说明: 7 | 8 | 用户:系统管理中的用户是指具体的个人用户,每个用户拥有自己的帐户和登录凭据。用户可以被分配给不同的用户组,并被授予特定页面和操作的权限。 9 | 10 | 用户组:用户组是一组用户的集合,可以根据角色、职能、权限等进行划分。用户组使得对多个用户进行管理更加方便,可以将相似权限的用户放入同一个用户组中。用户组可以被授予特定页面和操作的权限。 11 | 12 | ![系统1.png](https://static.cwoa.net/d57b878057db4948adb9e0ea0919d5d3.png) 13 | 14 | 15 | ## 定时任务 16 | 17 | 定时任务是预定的、自动执行的任务,根据设定的时间表和条件来运行。 18 | 19 | ![系统2.png](https://static.cwoa.net/d8f4764903fa453e9b146545a967b966.png) 20 | 21 | ## 审计日志 22 | 23 | 记录了系统中进行的各种操作的详细信息,包括操作的时间、执行者、操作类型、目标对象等 24 | 25 | ![系统3.png](https://static.cwoa.net/2e4c3f35390649ff9b038f442226973b.png) 26 | 27 | ## 令牌管理 28 | 29 | 在令牌管理中,包括Token认证令牌、令牌黑名单(JWT黑名单)和未处理令牌(未验证的JWT)。以下是对它们的说明: 30 | 31 | * Token认证令牌:Token认证令牌是一种用于身份验证和授权的令牌。通常使用JWT(JSON Web Token)作为Token认证令牌的格式。这种令牌由服务器颁发给用户,用于验证用户在系统中的身份和权限,以便进行安全的API请求和授权操作。 32 | 33 | * 令牌黑名单(JWT黑名单):令牌黑名单是指用于终止令牌的操作,将某个特定的Token认证令牌列入黑名单,使其在之后的请求中无效。这可以用于一些场景,如用户主动登出、密码被重置或用户账户被禁用。令牌黑名单允许服务器在验证令牌时,检查该令牌是否在黑名单中,从而拒绝已被加入黑名单的令牌的访问。 34 | 35 | * 未处理令牌(未验证的JWT):未处理令牌指的是在服务器端尚未进行验证和处理的JWT。这意味着服务器还没有对令牌进行身份验证、授权和其他相关的操作。未处理令牌可能是在服务器收到令牌后,但在进行验证之前的阶段。在这种情况下,服务器需要对令牌进行验证和处理,以确保令牌的有效性和合法性。 36 | 37 | ![系统4.png](https://static.cwoa.net/77db3143ec884d0c9bc21cf52555a592.png) 38 | -------------------------------------------------------------------------------- /site/version.md: -------------------------------------------------------------------------------- 1 | # 2.5 2 | 3 | * [Munchkin] Django Unfold 升级为0.33.0 4 | 5 | # 2.4 6 | 7 | * [Pilot] 优化主动消息触达动作 8 | * [Pilot] 新增 `帮助` 关键词: /help 9 | * [Pilot] 新增 联网检索能力: 10 | * /online_search - 切换为联网检索模式 11 | * /exit_online_search - 退出联网检索模式 12 | * [Pilot] 优化 使用虚拟队列区分Pilot的消息总线 13 | * [Pilot] 新增 `查看Jenkins任务列表` 关键词 14 | * /list_jenkins_jobs: 查看Jenkins任务列表 15 | * /jenkins_build_log: 查看Jenkins任务日志 16 | * /analyze_build_log: 分析Jenkins任务日志 17 | * /build_jenkins_pipeline: 构建Jenkins任务 18 | * [Munchkin] 机器人新增自动化技能模块 19 | * [Munchkin] 新增 知识集成 能力,支持自动化采集WeOps知识 20 | * [OCR Server] 新增Azure OCR支持 21 | 22 | # 2.3 23 | 24 | * [Classicfy Aiops Server] 新增经典AIOPS算法服务,内置时序预测、异常检查、根因分析、日志聚类算法 25 | * [Bionics] 新增图表生成服务,负责将时间序列指标生成图片 26 | * [Chunk Server] 新增 支持PDF扫描件识别 27 | * [Only Office] 新增 Only Office基础服务 28 | 29 | # 2.2 30 | 31 | * [基础服务] 新增SaltStack Server 32 | * [基础服务] 新增OCR Server 33 | * [Munchkin] 优化多处RAG解析细节 34 | * [Munchkin] 支持上传Zip格式的文件知识 35 | * [Munchkin] 优化 K8S调度支持使用Service Account 36 | * [Pilot] Pilot新增 `/reset`关键词 37 | * [ChatServer] 新增 `智谱AI公有云` 支持 38 | * [ChatServer] 优化 日志输出,API调用错误的时候提示异常原因 39 | * [ChunkServer] 优化 Word类型文档解析逻辑,标题和段落在初始拆分的时候合并一个Chunk 40 | * [ChunkServer] 优化 MD文件转换为Word解析 41 | * [ChunkServer] 修复 PPT解析过早return的bug 42 | * [RagServer] 优化 提取索引的Batch大小到参数中 43 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | > ⚠️ **重要提示** 2 | > 本项目 **OpsPilot** 已于近期 **合并至 [TencentBlueKing/bk-lite](https://github.com/TencentBlueKing/bk-lite/)** 仓库。后续的开发和维护将在新仓库中进行,欢迎前往新仓库查看最新进展与文档。 3 | 4 | # OpsPilot 5 | 6 | * [[English]](./Readme-cn.md) 7 | * [[中文]](./Readme.md) 8 | 9 | OpsPilot is an open source intelligent operation and maintenance assistant based on deep learning and LLM technology developed by the WeOps team. In the form of an operation and maintenance brain, it links various operation and maintenance systems to provide intelligent operation and maintenance capability support. 10 | 11 | 12 | 13 | 14 | 15 | It mainly supports Web, enterprise WeChat and other channels, providing users with extended capabilities in three directions: `Intelligent Q&A`, `ChatOps`, and `Intelligent Guidance`. 16 | 17 | # Documents 18 | 19 | https://wedoc.canway.net/opspilot/ 20 | 21 | # Discus Group 22 | 23 | 24 | 25 | # Inspire by 26 | 27 | * [Langchain-Chatchat](https://github.com/chatchat-space/Langchain-Chatchat) 28 | * [QAnything](https://github.com/netease-youdao/QAnything) 29 | * [ragflow](https://github.com/infiniflow/ragflow) 30 | 31 | # Star History 32 | 33 | [![Star History Chart](https://api.star-history.com/svg?repos=WeOps-Lab/OpsPilot&type=Date)](https://star-history.com/#WeOps-Lab/OpsPilot&Date) 34 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "rag-server"] 2 | path = rag-server 3 | url = https://github.com/WeOps-Lab/rag-server.git 4 | [submodule "chat-server"] 5 | path = chat-server 6 | url = https://github.com/WeOps-Lab/chat-server.git 7 | [submodule "chunk-server"] 8 | path = chunk-server 9 | url = https://github.com/WeOps-Lab/chunk-server.git 10 | [submodule "bce-embed-server"] 11 | path = bce-embed-server 12 | url = https://github.com/WeOps-Lab/bce-embed-server 13 | [submodule "fast-embed-server"] 14 | path = fast-embed-server 15 | url = https://github.com/WeOps-Lab/fast-embed-server 16 | [submodule "ocr-server"] 17 | path = ocr-server 18 | url = https://github.com/WeOps-Lab/ocr-server 19 | [submodule "pandoc-server"] 20 | path = pandoc-server 21 | url = https://github.com/WeOps-Lab/pandoc-server 22 | [submodule "bionics"] 23 | path = bionics 24 | url = https://github.com/WeOps-Lab/bionics 25 | [submodule "classicfy-aiops-server"] 26 | path = classicfy-aiops-server 27 | url = https://github.com/WeOps-Lab/classicfy-aiops-server 28 | [submodule "munchkin-web"] 29 | path = munchkin-web 30 | url = https://github.com/WeOps-Lab/munchkin-web.git 31 | [submodule "munchkin"] 32 | path = munchkin 33 | url = https://github.com/WeOps-Lab/munchkin.git 34 | [submodule "pilot"] 35 | path = pilot 36 | url = https://github.com/WeOps-Lab/pilot.git 37 | [submodule "kube-service"] 38 | path = kube-service 39 | url = https://github.com/WeOps-Lab/kube-service 40 | -------------------------------------------------------------------------------- /site/quick-start.md: -------------------------------------------------------------------------------- 1 | # Quick Start 2 | 3 | ## Deploy K3S 4 | 5 | ``` 6 | curl https://releases.rancher.com/install-docker/20.10.sh | sh 7 | curl -sfL https://get.k3s.io | sh -s - --docker 8 | ``` 9 | 10 | ## Get Pilot image 11 | 12 | ``` 13 | docker pull ccr.ccs.tencentyun.com/megalab/pilot 14 | ``` 15 | 16 | ## Create namespace 17 | 18 | ``` 19 | kubectl create ns ops-pilot 20 | ``` 21 | 22 | ## Deploy basic components 23 | 24 | Enter the `installer/depend` directory and execute 25 | 26 | ``` 27 | kubectl apply -f elasticsearch.yml 28 | kubectl apply -f minio.yml 29 | kubectl apply -f postgres.yml 30 | kubectl apply -f rabbitmq.yml 31 | kubectl apply -f pandoc-server.yml 32 | kubectl apply -f bionics.yml 33 | ``` 34 | 35 | ## Deploy service components 36 | 37 | Enter the `installer/ai-service` directory and execute 38 | 39 | ``` 40 | kubectl apply -f bce-embed-server.yml 41 | kubectl apply -f bce-rerank-server.yml 42 | kubectl apply -f chat-server.yml 43 | kubectl apply -f chunk-server.yml 44 | kubectl apply -f fast-embed-server-zh.yml 45 | kubectl apply -f rag-server.yml 46 | kubectl apply -f classicfy-aiops-server.yml 47 | ``` 48 | 49 | ## Optional components 50 | 51 | ``` 52 | kubectl apply -f ./saltstack-server.yml 53 | ``` 54 | 55 | ## Deploy Munchkin 56 | 57 | Enter the `installer/munchkin` directory and execute 58 | 59 | ``` 60 | kubectl apply -f ./configmap.yml 61 | kubectl apply -f ./svc.yml 62 | kubectl apply -f ./ingress.yml #Modify YOUR_HOST configuration 63 | kubectl apply -f ./munchkin-sa.yml 64 | kubectl apply -f ./munchkin.yml 65 | ``` -------------------------------------------------------------------------------- /site/api/aiops/anomaly/abod.md: -------------------------------------------------------------------------------- 1 | # ABOD 2 | 3 | ## Algorithm introduction 4 | 5 | In high dimensions, distance is homogenized, and Angle is more stable than distance. Therefore, angle-based Outlier Detection (ABOD) focuses on the Angle formed by any three data points in a set of multivariate feature Spaces, and the circumference of the Angle is different for outliers and normal points. Therefore, the anomaly is detected 6 | 7 | ## Use scenario 8 | 9 | It is suitable for high-dimensional multi-indicator anomaly detection (the number of indicators is greater than 25). The higher the data dimension, the better the algorithm performance. The smaller the number of indicators, the lower the algorithm accuracy, and the higher the time cost of the algorithm. You can measure all data points for anomalies. The higher the anomaly, the more likely it is to be an anomaly. The threshold can be adjusted based on the actual situation 10 | 11 | ## Algorithm principle 12 | 13 | ![Excalidraw Image](./img/ABOD.png) 14 | 15 | The main idea of the algorithm is to judge outliers by comparing the Angle of the difference vector between data points. By calculating the Angle change of the difference vector, the algorithm can capture the difference and offset between data points and other points, and then identify potential outliers. Because the algorithm does not depend on the selection of any parameter, the influence of subjective factors on the anomaly detection results can be reduced 16 | 17 | * the original link: https://www.dbs.ifi.lmu.de/Publikationen/Papers/KDD2008.pdf -------------------------------------------------------------------------------- /site/api/aiops/anomaly/knn.md: -------------------------------------------------------------------------------- 1 | # KNN 2 | 3 | ## Algorithm introduction 4 | 5 | K-NearestNeighbor (KNN) algorithm is a distance-based unsupervised machine learning anomaly detection algorithm. Outliers must be far away from most normal data points. Based on this idea, KNN only needs to compute the distance between each data point and its nearest K samples in turn, and then compare the distance with the threshold value to obtain the outliers. 6 | ## Use scenario 7 | 8 | It is suitable for anomaly detection when does not know the data distribution , and is not suitable for high-dimension data , and because only outliers can be found and abnormal clusters cannot be found, each calculation distance needs to traverse the entire data set, and the time complexity is high. 9 | 10 | ## Algorithm principle 11 | ![Excalidraw Image](./img/KNN.png)
12 | 13 | (1) Calculate the distance between each data point in the data set and each other, using Euclidean distance as the distance measure by default; 14 | 15 | (2) Sort in order of increasing distance, select K points with the smallest distance from the current point (K value is selected according to the specific needs of the problem and experimental experience, the default is 5) 16 | 17 | (3) Calculate the distance between the current point and K neighbors, and take the mean or median value and maximum value (set by the parameter method) as the outlier. The larger the outlier, the more likely it is to be the outlier. 18 | 19 | **Links to**: -------------------------------------------------------------------------------- /site/api/aiops/anomaly/oneclasssvm.md: -------------------------------------------------------------------------------- 1 | # One-Class SVM 2 | ## Algorithm introduction 3 | 4 | One-class SVM is a classical unsupervised machine learning algorithm in which there is only One Class of training data, the normal sample, and no abnormal sample. The goal of a One-Class SVM is to learn a hyperplane that separates the positive sample from the origin while maximizing the distance between the hyperplane and the origin. Unlike the ordinary binary classification problem, the one-class SVM has only One Class, and not all of the classes are judged as "exceptions". 5 | 6 | ## Use scenario 7 | It is suitable for anomaly detection when has little or no abnormal data, and there is a large gap between normal and abnormal samples in the feature space . 8 | 9 | ## Algorithm principle 10 | ![Excalidraw Image](./img/OCSVM.png)
11 | 12 | In the training stage of the algorithm, it is first necessary to collect the data of normal samples, which do not contain abnormal samples, map the data to a high-dimensional feature space with appropriate kernel functions, and train the One-Class SVM model in the high-dimensional feature space to separate the normal samples from the origin and maximize the interval between them. In the prediction stage, for each new sample, the trained model is used to calculate the distance from the sample to the hyperplane or the value of the decision function. If the value of the distance or decision function exceeds the preset threshold, it is classified as an abnormal sample. 13 | 14 | **the original link** : -------------------------------------------------------------------------------- /site/api/aiops/anomaly/suod.md: -------------------------------------------------------------------------------- 1 | # Suod 2 | 3 | ## Algorithm introduction 4 | 5 | Training or using a large number of unsupervised models to make predictions will face huge overhead problems, especially on high-dimensional and big data, and in many cases even convergence is impossible, so SUOD is proposed. SUOD is a heterogeneous unsupervised model. With JL Projection as the solution to high-dimensional problems, approximate regressor is used instead of unsupervised models to accelerate the prediction process, and balanced parallel scheduling is performed for model training to improve system performance. 6 | 7 | ## Use scenario 8 | 9 | This algorithm is suitable for the case that the data dimension is high and the processing speed is required 10 | 11 | ## Algorithm principle 12 | ![Excalidraw Image](./img/SUOD.png) 13 | 14 | To put it simply, after inputting x_train training data, it will first reduce the dimension of high-dimensional training data, and then train multiple basic models in parallel and get the weight of each model, and save the y_train obtained by training. x_train and y_train are then used to train the approximate model (using random forest by default). If the approximate model performs better than the base model, the base model will be replaced. When x_text is input to detect anomalies in the data, the trained approximate model/ basic model will be called to calculate the anomaly score for each sample, weighted to obtain the final integrated anomaly score, and then compare the anomaly score with the threshold value. 15 | 16 | **Links to** : -------------------------------------------------------------------------------- /site/api/aiops/anomaly/ecod.md: -------------------------------------------------------------------------------- 1 | # ECOD 2 | 3 | ## Algorithm introduction 4 | 5 | The Empirical Cumulative Outlier Detection (ECOD) algorithm is an unsupervised anomaly detection algorithm. The core idea is to calculate the probability of outliers by using the experience cumulative distribution function (ECDF) to estimate the joint cumulative distribution function of the data (calculating the outlier score for each sample by combining the outlier scores of different dimensions of the same sample). The algorithm was inspired by the fact that outliers are usually rare events that appear at the tail of a distribution. 6 | 7 | ## Use scenario 8 | 9 | Anomaly detection for high-dimensional data and want interpretive results , can understand which indicators are more likely to cause data point anomalies , with low time and spatial complexity. The processing can be accelerated by parallel computation. 10 | ## Algorithm principle 11 | 12 | ![Excalidraw Image](./img/ECOD.png)
13 | 14 | The algorithm first calculates the left-tail ECDF and right-tail ECDF of each dimension (index), then calculates the skewness of each dimension, and finally performs probabilistic aggregation based on this. After traversing each data point, Oleft-only is obtained by left-tailed ECDF aggregation, and Oright-only is obtained by right-tailed ECDF aggregation. Oauto is calculated according to skewness, and the maximum values of the three are taken as the outliers of the data points, and the threshold can be set to screen out the outliers. 15 | 16 | ** Paper Links ** : -------------------------------------------------------------------------------- /site/api/aiops/logreduce/drain3.md: -------------------------------------------------------------------------------- 1 | # Drain3 2 | 3 | ## Algorithm introduction 4 | 5 | Drain is an online log parsing method proposed in 2017. Drain3 revamps Drain so that it can be used under Python3 and in actual production environments. The core idea of Drain3 is the same as Drain, which is based on the assumption that the number of words generated by the same log template is the same after word segmentation. A Parse Tree composed of the log length, prefix words, and log template is created under the word assumption 6 | 7 | ## Use scenario 8 | 9 | This algorithm is suitable for 'real-time analysis and analysis' of logs, with high accuracy and efficiency 10 | 11 | ## Algorithm principle 12 | 13 | ![Drain3](./img/drain3.png) 14 | 15 | For the input logs, regular expressions are used to replace common variables, and then words are divided. Logs are divided into different sub-nodes according to the length of the word segmentation, and then into different groups according to the first word segmentation. After the logs are divided into the corresponding log groups bucket, the similarity between the logs and the mode of each group will be calculated, and the maximum value will be compared with the threshold value. If the similarity is greater than the threshold value, the logs will be classified into the corresponding group, and the parts of the mode that are different from the logs will be replaced with *, and the mode will be returned. If the similarity is less than the threshold, a new group is created, the pattern of the group is the log itself, and it is returned. The following is an example of Drain3 mode discovery for logs 16 | 17 | ![Drain3](./img/drain3_example.png) 18 | 19 | 20 | ## Paper link 21 | 22 | https://jiemingzhu.github.io/pub/pjhe_icws2017.pdf -------------------------------------------------------------------------------- /site/configs/endpoint.md: -------------------------------------------------------------------------------- 1 | # EndPoint配置 2 | 3 | EndPoint配置存放在`endpoint.yml`文件中 4 | 5 | ## Action Server配置 6 | 7 | action_endpoint指向Rasa Action Server的地址,当触发Action的时候,NLU Server会调用Action Server的接口,单机部署的话,使用默认配置即可 8 | 9 | ``` 10 | action_endpoint: 11 | url: "http://127.0.0.1:5055/webhook" 12 | ``` 13 | 14 | ## 远程模型加载配置 15 | 16 | ### Rasa远程模型加载 17 | 18 | models.url指向Rasa模型的地址,wait_time_between_pulls指定了模型拉取的间隔时间,单位是秒。 19 | 假如远端服务没有返回`ETag`,请将`wait_time_between_pulls`设置为`null`,否则会导致模型不断被拉取,NLU Server不断重启的情况 20 | 21 | ``` 22 | models: 23 | url: 24 | wait_time_between_pulls: null 25 | ``` 26 | 27 | ## Tracker配置 28 | 29 | Tracker记录了用户对话的状态以及历史记录 30 | 31 | ### SQLite Tracker 32 | 33 | 一般使用SQLite Tracker就够用了~ 34 | 35 | ```yaml 36 | tracker_store: 37 | type: SQL 38 | dialect: "sqlite" 39 | url: "" 40 | db: "tracker.db" 41 | username: 42 | password: 43 | ``` 44 | 45 | ### Postgres Tracker配置 46 | 47 | 当需要多个NLU Server共享Tracker的时候,可以使用Postgres Tracker 48 | 49 | ```yaml 50 | tracker_store: 51 | type: SQL 52 | dialect: "postgresql" 53 | url: "localhost" 54 | db: "postgres" 55 | username: "postgres" 56 | password: "password" 57 | ``` 58 | 59 | ## Event Broker配置 60 | 61 | Event Broker用于将用户的对话事件发送到指定的服务,一般用于做消息的记录 62 | 63 | ### Postgres Event Broker 64 | 65 | ```yaml 66 | event_broker: 67 | type: SQL 68 | url: 127.0.0.1 69 | port: 5432 70 | dialect: postgresql 71 | username: postgresql 72 | password: 73 | db: ops-pilot 74 | ``` 75 | 76 | ## Lock Store配置 77 | 78 | 在多个NLU Server共享Tracker的时候,需要使用Lock Store来保证Tracker的顺序正确,默认用的是`InMemoryLockStore`,不会保证多个NLU 79 | Server的Tracker的顺序正确 80 | 81 | ### Redis Lock Store 82 | 83 | ```yaml 84 | lock_store: 85 | type: "redis" 86 | url: 87 | port: 6379 88 | password: 89 | db: 1 90 | key_prefix: ops-pilot 91 | ``` -------------------------------------------------------------------------------- /site/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | # https://vitepress.dev/reference/default-theme-home-page 3 | layout: home 4 | 5 | hero: 6 | name: "OpsPilot" 7 | text: "Virtual SRE" 8 | tagline: "" 9 | actions: 10 | - theme: brand 11 | text: Quick Start 12 | link: /quick-start 13 | - theme: alt 14 | text: Introduction 15 | link: /introduction 16 | 17 | features: 18 | - title: 🎓Knowledge Q&A 19 | details: Leveraging LLM technology to provide domain-specific knowledge Q&A capabilities, including service desk portal knowledge Q&A, IM knowledge Q&A, and intelligent ticket summarization. 20 | - title: 🚀ChatOps 21 | details: Utilizing NLP technology and Rich Component capabilities, enabling operational tasks to be completed within chat environments. Provides features such as server status checks and real-time security scanning. 22 | - title: 🌟Intelligent Guidance 23 | details: Innovatively combines predictive dialogue flows with advanced models, enabling OpsPilot to offer intelligent conversational guidance. This includes intelligent ticket submission guidance and smart incident handling guidance 24 | - title: 📲Multi-Channel Support 25 | details: Offers multi-channel access support, including Web, WeChat, DingTalk, Enterprise WeChat, Slack, and more, allowing users to utilize OpsPilot within their familiar tools. 26 | - title: 👋Rich AIOPS Models 27 | details: Provides a comprehensive suite of AIOPS algorithms, including time series forecasting, anomaly detection, root cause analysis, and other AIOPS models. Extracts implicit knowledge from operational data. 28 | - title: 🎁Comprehensive Integration Capabilities 29 | details: Offers extensive integration capabilities, enabling system integration with Kubernetes, SaltStack, WeOps Lite, and more, to achieve the goal of automated operational management. 30 | --- 31 | -------------------------------------------------------------------------------- /site/api/aiops/anomaly/inne.md: -------------------------------------------------------------------------------- 1 | # INNE 2 | 3 | ## Algorithm introduction 4 | 5 | In order to overcome the problem that IForest algorithm is not good at dealing with local relatively sparse points in numerical data and is not suitable for data with particularly high dimensions, etc., Isolation‐Based Anomaly Detection Using Nearest‐Neighbor Ensembles (INNE) using isolation mechanism and nearest ‐ neighbor ensembles (INNE), The isolation mechanism is realized by cutting data space by multi-dimensional hypersphere, and the local distribution of data is considered. 6 | 7 | ## Use scenario 8 | Applicable to anomaly detection of low correlation index data , this algorithm can well adapt to abnormal situations in different data sets, and can conveniently handle high-dimension data to capture local anomalies in high-dimensional space. 9 | 10 | ## Algorithm principle 11 | ![Excalidraw Image](./img/INNE.png)
12 | 13 | In the training stage, t subsamples are randomly selected from the training set to build a hypersphere set. The nearest neighbor search is carried out for each data point to find the nearest neighbor, and the minimum hypersphere radius is calculated based on the attributes of the neighbor, so that the hypersphere can overcontain the current data point and its neighbors. In the test phase, the data points of each test are put into each hypersphere to calculate the isolation score, which is calculated according to the ratio of the relative size of the hypersphere in which it is located to the size of the neighbor hypersphere, and then the average value is taken as the final outlier. 14 | 15 | **Link to original paper** : -------------------------------------------------------------------------------- /site/api/aiops/causation/fpgrowth.md: -------------------------------------------------------------------------------- 1 | # FP-Growth 2 | 3 | ## Algorithm introduction 4 | 5 | Frequent pattern growth (fp-growth) algorithm is a data mining algorithm for mining frequent item sets. Based on the prefix tree data structure (called FP tree), it can efficiently discover frequent item sets by using the local properties of frequent items and the compression technique of prefix tree. The main idea of FP-growth algorithm is to construct FP tree first, and then discover frequent item sets by traversing FP tree and constructing conditional pattern basis 6 | 7 | ## Use scenario 8 | 9 | This algorithm is suitable for processing large-scale and high-dimensional data, and it is also an unsupervised learning method, which is suitable for the case of no labels 10 | 11 | ## Algorithm principle 12 | 13 | The advantage of the FP-growth algorithm is that it only needs to scan the data set twice, so it is more efficient than Apriori. In addition, the FP-growth algorithm uses compression techniques to reduce the need for storage space and can handle large data sets. With the FP-growth algorithm, we can find frequent item sets, that is, sets of items that often appear together. The specific steps of the algorithm are as follows: 14 | 15 | (1) Traverse the data set, calculate the support degree of each item, and sort according to the support degree in descending order; 16 | 17 | (2) Construct FP tree: traverse the data set, sort each transaction according to the support degree of frequent items in descending order, and insert the sorted transactions into the FP tree; 18 | 19 | (3) The conditional schema base (constructed by the prefix path of the node) of each node in the FP tree is recursively mined for frequent item sets; 20 | 21 | (4) The conditional pattern tree is constructed according to the conditional pattern base, and then the conditional pattern tree is recursively mined; 22 | 23 | (5) Repeat steps 3 and 4 until there are no more frequent item sets to mine. -------------------------------------------------------------------------------- /site/api/aiops/anomaly/iforest.md: -------------------------------------------------------------------------------- 1 | # IForest 2 | 3 | ## Algorithm introduction 4 | 5 | Isolation Forest (IForest) is an Ensemble based unsupervised anomaly detection method with linear time complexity and high accuracy. IForest uses an efficient strategy in that dense clusters need to be cut many times to separate each data point into a separate subspace, while low-density points can easily be split into a subspace. 6 | 7 | ## Use scenario 8 | It is suitable for anomaly detection of continuous data , and can be used for data sets with large data scale (the number of trees can be increased to increase the algorithm stability, each tree is independent of each other. is not applicable to data with too large dimensions , which will reduce the reliability of the algorithm. 9 | 10 | ## 3. Algorithm principle 11 | ![Excalidraw Image](./img/IForest.png) 12 | 13 | The algorithm adopts a two-stage process for anomaly detection. The first stage is the training stage, which subsamples the training set data and divides the training set by recursion until the data points are isolated or reach limited hegiht, so as to construct a series of isolated trees (ITrees). During the construction of each isolated tree, the segmentation index is randomly selected, and the segmentation value is generated between the maximum and minimum index value. The second stage is the evaluation stage. Each data point is passed through each iTree, and the Average Path Length (APL) of each data point on all itrees is calculated to measure the abnormal score, and the abnormal score is obtained by normalizing APL in the range of 0-1. An anomaly score much less than 1 indicates a definite normal, and the closer it is to 1, the more likely it is to be an outlier (outliers are far from dense clusters and can easily be assigned to a subspace, so the average path length will be shorter, such as A in iTree1). 14 | 15 | **the original link**: -------------------------------------------------------------------------------- /site/api/aiops/anomaly/kpca.md: -------------------------------------------------------------------------------- 1 | # KPCA 2 | 3 | 4 | Algorithm Overview 5 | 6 | Kernel Principal Component Analysis (KPCA) is a nonlinear extension method of Principal Component Analysis (PCA). Since operational data often contains complex temporal dependencies, trends, etc., the distribution of operational data is usually nonlinear, so KPCA is more suitable for anomaly detection than PCA. KPCA maps the training data to an infinite-dimensional feature space and extracts the principal components of the data distribution from this space. It reconstructs the data using the principal components and indicates the degree of anomaly by calculating the reconstruction error. 7 | 8 | ## Usage Scenarios 9 | 10 | It is suitable for nonlinear data distribution, with complex data structures for anomaly detection, and traditional linear methods such as PCA cannot accurately capture the underlying patterns in the data. If the data structure is complex, KPCA can handle complex data better by using kernel functions and an infinite-dimensional feature space. 11 | 12 | #### 3. Algorithm Principle 13 | 14 | ![Excalidraw Image](./img/KPCA.png) 15 | 16 | (1) Data preprocessing: Cleaning, standardizing, or normalizing the input data; 17 | 18 | (2) Data mapping: Using selected kernel functions to map the data to an infinite-dimensional feature space. Common kernel functions include Gaussian kernel functions and polynomial kernel functions; 19 | 20 | (3) Feature extraction: Applying KPCA to extract the principal components of the data in the mapped feature space. This can be achieved through steps such as calculating the similarity matrix, centering the Gram matrix, and extracting feature vectors; 21 | 22 | (4) Calculating the reconstruction error: Reconstruct the data using the extracted principal components and calculate the reconstruction error (i.e. the gap between the original data and the reconstructed data); 23 | 24 | (5) Anomaly detection: Use the reconstruction error as an anomaly measure and classify the data into normal or anomalous by setting a threshold. 25 | 26 | **Paper original link**: [https://www.heikohoffmann.de/documents/hoffmann_kpca_preprint.pdf](https://www.heikohoffmann.de/documents/hoffmann_kpca_preprint.pdf) -------------------------------------------------------------------------------- /Readme-cn.md: -------------------------------------------------------------------------------- 1 | `` 2 | 3 | # OpsPilot 4 | 5 | * [[English]](./Readme-en.md) 6 | * [[中文]](./Readme.md) 7 | 8 | OpsPilot is an open source intelligent operation and maintenance assistant based on deep learning and LLM technology developed by the WeOps team. In the form of an operation and maintenance brain, it links various operation and maintenance systems to provide intelligent operation and maintenance capability support. 9 | 10 | ![Architecture diagram.jpg](https://static.cwoa.net/01adc49936ae41d68dded993461a7dd0.jpg) 11 | 12 | It mainly supports Web, enterprise WeChat and other channels, providing users with extended capabilities in three directions: `Intelligent Q&A`, `ChatOps`, and `Intelligent Guidance`. 13 | 14 | #Official documentation 15 | 16 | https://wedoc.canway.net/opspilot/ 17 | 18 | # RoadMap 19 | 20 | * [ ] RAG detail processing optimization, overall code optimization 21 | * [ ] Introducing aiops-server: built-in classic aiops algorithm 22 | * [ ] Pilot message bus optimization 23 | * [ ] Pilot supports access to Gitlab and AI Code Review 24 | * [ ] Pilot supports access to Loki and Graylog to provide log insight capabilities 25 | * [ ] Pilot supports access to Prometheus to provide monitoring indicator insights. 26 | * [ ] Pilot supports access to SaltStack and provides ChatOps capabilities 27 | * [ ] Pilot supports access to Kubernetes and provides K8S cluster insight capabilities 28 | * [ ] Pilot supports access to WeOps Lite, providing CMDB RAG and insight capabilities 29 | * [ ] Pilot supports access to Tempo to provide APM insight capabilities 30 | * [ ] OpsPilot UI replacement, providing a smoother UI interface 31 | 32 | # Discussion group 33 | 34 | Add Xiaojiaqi WeChat and Xiaojiala group 35 | 36 | 37 | 38 | # Inspireby 39 | 40 | * [Langchain-Chatchat](https://github.com/chatchat-space/Langchain-Chatchat) 41 | * [QAnything](https://github.com/netease-youdao/QAnything) 42 | * [ragflow](https://github.com/infiniflow/ragflow) 43 | 44 | # StarHistory 45 | 46 | [![Star History Chart](https://api.star-history.com/svg?repos=WeOps-Lab/OpsPilot&type=Date)](https://star-history.com/#WeOps-Lab/OpsPilot&Date) 47 | -------------------------------------------------------------------------------- /site/features/bot.md: -------------------------------------------------------------------------------- 1 | # 机器人管理 2 | 3 | 机器人管理模块主要用于对Pilot进行管理,在这里可以对Pilot进行上线、下线,回复规则与对话记录管理等操作 4 | 5 | ## 1.机器人 6 | 7 | 为了适用不同的场景,比如服务台知识库问答,运维专门问答等场景,可以设置不同的机器人,一个机器人对应一个Pilot,Pilot被K8S所调度,每个Pilot本质上是一个Pod。 8 | 9 | ### 1.1机器人列表 10 | 11 | 机器人列表展示了所有创建的机器人,支持对机器人进行上线/下线。上线的机器人可以正常运行,通过配置前端对话框响应与其交互的请求;下线的机器人则停止工作,不再响应请求。 12 | 13 | ![机器人列表.png](https://static.cwoa.net/f1037ad159e5495f89ea470fe345f8ab.png) 14 | 15 | ### 1.2 机器人配置 16 | 17 | 对每个机器人进行基础模型和LLM技能的配置,让该机器人具备对应能力,此外还可以配置消息通道,以便更好触达用户。 18 | 19 | ![机器人.png](https://static.cwoa.net/15e9cda0c5b046cf9f63403e40917bb3.png) 20 | 21 | **基本信息** 22 | 23 | 针对每一台机器人,你都可以设置其名称、ID、描述等基本信息。基本信息有助于理解机器人的作用和状态,并且可以作为识别和搜索的条件。 24 | 25 | ![机器人基本信息.png](https://static.cwoa.net/2b56e9b613fa4aea856b34cae270c360.png) 26 | 27 | **模型设置** 28 | 29 | 为该机器人选择一个基础模型进行服务,基础模型是机器人在进行意图识别、语言处理等任务时所依赖的基本AI模型。目前已经内置了核心模型,其他模型语料撰写和模型训练可以在“拓展包-模型”中进行。 30 | 31 | **LLM模型** 32 | 33 | 为该机器人选择对应的LLM技能,比如开放知识问答、自动化执行等等,LLM是在基础模型上增加的技能包,可以提供更精细、更高级的语言理解和任务执行。对于LLM模型,目前已经内置了基于ChatGPT的开放问答技能,其他更多技能可在“AI模型-LLM模型”中拓展。 34 | 35 | ![机器人技能.png](https://static.cwoa.net/e34ad2069a1e49838a4866f950983ca4.png) 36 | 37 | **通道** 38 | 39 | 为了满足使用者多渠道的使用需求,机器人支持设置与用户进行交互的通道,比如Web、企微、钉钉等,通道配置,可以使机器人更好地为用户提供服务。 40 | 41 | **高级设置** 42 | 43 | 支持为该机器人设置域名/SSL/域名等设置,便于设置用户/管理员如何访问该机器人 44 | 45 | ![机器人设置.png](https://static.cwoa.net/7e92e9f59a54466082fc582f7e2c716d.png) 46 | 47 | ## 2.对话记录 48 | 49 | 对话记录里面记录了每个机器人与用户的对话记录,可以用于对话记录的审计、标注、以及人工介入等场景 50 | 51 | ![机器人对话.png](https://static.cwoa.net/8f262863d588432ab18534a3ac86d8ed.png) 52 | 53 | ## 3.对话规则 54 | 55 | 有时候希望同一个机器人在同一个问题的时候, 可以针对不同的用户使用不同的大模型技能,这个时候就可以在对话规则中进行配置。每个规则可以配置生效的机器人、使用的技能、技能提示词以及生效的用户和用户组。 56 | 57 | ![机器人规则.png](https://static.cwoa.net/a8fffbd2826644d584597114a6803952.png) 58 | 59 | ## API 60 | 61 | ### 执行机器人对话 62 | 63 | > POST /api/bot/skill_execute/ 64 | 65 | ``` 66 | { 67 | "bot_id": 1, 68 | "skill_id": "action_llm_fallback", 69 | "user_message": "你是谁", 70 | "sender_id":"", 71 | "chat_history": [ 72 | ] 73 | } 74 | ``` 75 | 76 | ### 主动消息推送 77 | 78 | > POST /conversations/{sender_id}/trigger_intent 79 | 80 | ``` 81 | { 82 | "name": "EXTERNAL_UTTER", 83 | "entities": { 84 | "external_utter_content": "你好呀" 85 | "external_utter_channel": "enterprise_wechat" 86 | } 87 | } 88 | ``` 89 | -------------------------------------------------------------------------------- /site/api/aiops/anomaly/xgbod.md: -------------------------------------------------------------------------------- 1 | # XGBOD 2 | ## Algorithm introduction 3 | 4 | Extreme Boosting Based Outlier Detection (XGBOD) algorithm is a semi-supervised ensemble algorithm for improving supervised outlier detection, which extends the original feature space by various unsupervised outlier detection functions. The greedy algorithm is used to prune the augmented feature space to control the computational complexity. Finally, XGBoost is used as the final output classifier of the refined feature space. 5 | 6 | ## Use scenario 7 | 8 | Applicable to anomaly detection of labeled or partially labeled data , capable of detecting and utilizing more information in high-dimensional feature space, capable of generating various accuracy and diversity of TOS by adjusting the parameters of the basic unsupervised model. Suitable for situations where performance needs to be improved with a balance between accuracy and variety. 9 | 10 | ## Algorithm principle 11 | ![Excalidraw Image](./img/XGBOD.png) 12 | 13 | XGBOD algorithm is divided into three stages, which are feature transformation stage, TOS selection stage and final prediction stage: 14 | 15 | (1) Feature transformation stage: The outlier score TOS is obtained through a variety of unsupervised outlier detection methods. The algorithm applies different unsupervised outlier detection methods as the basic anomaly scoring function, and adjusts their parameters to produce TOS with different accuracy and diversity. These TOS are regarded as new features to improve the original feature space. 16 | 17 | (2) TOS selection stage: Select a part of the generated TOS collection and combine it with the original features. In order to select TOS, the algorithm proposed three selection methods: random selection, accurate selection and balanced selection. Random selection can produce more uncertain and unstable results, and balanced selection works better on datasets with more features (indicators), while balanced selection works better on datasets with fewer features (indicators). The selected TOS is combined with the original features to form an improved feature space. 18 | 19 | (3) Final prediction stage: train the XGBoost classifier to output the final anomaly detection result. 20 | 21 | **the original link**: -------------------------------------------------------------------------------- /site/api/aiops/timeseries/holtwinter.md: -------------------------------------------------------------------------------- 1 | # Holt-Winter 2 | 3 | ## Algorithm introduction 4 | 5 | The Holt-Winter method is actually three exponential smoothing. The closer to the predicted point, the greater the effect, so the weight according to the exponential attenuation, this is the basic idea of exponential smoothing. All exponential smoothing methods update the results of the previous time step calculation and use the new information contained in the current time step data by "mixing" the old and new information and controlling the weight of the old and new information. 6 | ## Use scenario 7 | For three exponential smoothing methods: 8 | 9 | (1) An Exponential smoothing is aimed at sequences with and no trend or seasonality ; 10 | (2) Holt exponential smoothing is a series of with trend but no seasonal ; 11 | (3) Holt-Winters exponential smoothing is aimed at sequences with and seasonal . 12 | Data should be preprocessed before using Holt-Winter. 13 | 14 | ## Algorithm principle 15 | ![Excalidraw Image](./img/Holt.png) 16 | 17 | In an exponentially smoothed recurrence relationship, it can be seen that the smoothed value at the time step i(i th time point) is the weighted sum of the actual data xi at the current time and the previously smoothed value si-1, and α controls the balance (weight) of the old and new information. All previous observations have an effect on the current smoothing value, but their role diminishes as the power of the parameter α increases, and the predicted value of an exponential smoothing is si. 18 | 19 | Quadratic exponential smoothing takes the trend as an additional consideration on this basis. It is necessary to update the state of the smoothed signal and the smoothed trend two quantities (the trend is processed by the first exponential smoothing, and β controls the balance). The predicted value takes the smoothed signal and trend into account at the same time and takes the last smoothed value. Each time step is then increased to add a final smoothing trend to the smoothing value. 20 | 21 | The three exponential smoothing increases the periodic pi and adds the seasonal component on the basis of the first two. At the same time, the seasonal component is also exponentially smoothed, and the forecast value takes into account all three. -------------------------------------------------------------------------------- /site/api/saltstack_server.md: -------------------------------------------------------------------------------- 1 | SaltStack Server is used to provide automation capabilities for OpsPilot 2 | 3 | ## SaltStack Server 4 | 5 | ### example 6 | 7 | ```python 8 | import json 9 | import requests 10 | 11 | SALT_API_URL = "http://saltstack-server.ops-pilot" 12 | SALT_API_USERNAME = "saltapi" 13 | SALT_API_PASSWORD = "password" 14 | 15 | 16 | def get_token(): 17 | headers = { 18 | 'Accept': 'application/json', 19 | 'Content-Type': 'application/json', 20 | } 21 | data = { 22 | 'username': SALT_API_USERNAME, 23 | 'password': SALT_API_PASSWORD, 24 | 'eauth': 'pam', 25 | } 26 | response = requests.post(f"{SALT_API_URL}/login", headers=headers, json=data) 27 | response.raise_for_status() 28 | return response.json()['return'][0]['token'] 29 | 30 | 31 | def execute_salt_command(client, func, tgt, args=None): 32 | token = get_token() 33 | headers = { 34 | 'Accept': 'application/json', 35 | 'Content-Type': 'application/json', 36 | 'X-Auth-Token': token, 37 | } 38 | data = {"client": client, 'fun': func, 'tgt': tgt} 39 | if args: 40 | data['arg'] = args 41 | response = requests.post(SALT_API_URL, headers=headers, json=data, verify=False) 42 | response.raise_for_status() 43 | return response.json() 44 | 45 | 46 | def execute_local(func, tgt, args=None): 47 | return execute_salt_command('local', func, tgt, args) 48 | 49 | 50 | def execute_local_async(func, tgt, args=None): 51 | return execute_salt_command('local_async', func, tgt, args) 52 | 53 | 54 | def find_job(jid): 55 | token = get_token() 56 | headers = { 57 | 'Accept': 'application/json', 58 | 'Content-Type': 'application/json', 59 | 'X-Auth-Token': token, 60 | } 61 | response = requests.get(f'{SALT_API_URL}/jobs/{jid}', headers=headers, verify=False) 62 | response.raise_for_status() 63 | return response.json() 64 | 65 | 66 | def execute_ssh(func, tgt, args=None): 67 | return execute_salt_command('ssh', func, tgt, args) 68 | 69 | 70 | def execute_runner(func, tgt, args=None): 71 | return execute_salt_command('runner', func, tgt, args) 72 | 73 | 74 | def execute_wheel(func, tgt, args=None): 75 | return execute_salt_command('wheel', func, tgt, args) 76 | 77 | 78 | # 示例调用 79 | if __name__ == "__main__": 80 | response = execute_ssh('test.ping', '127.0.0.1') 81 | print(json.dumps(response, indent=4)) 82 | 83 | ``` -------------------------------------------------------------------------------- /site/api/aiops/timeseries/sarima.md: -------------------------------------------------------------------------------- 1 | # SARIMA 2 | ## Algorithm introduction 3 | 4 | SARIMA (Seasonal Autoregressive Integrated Moving Average) is a statistical model for time series forecasting that extends the ARIMA (autoregressive Integrated Moving Average) model. It is difficult for general time series data to meet the stationarity requirements, and the most commonly used conversion method is difference, so ARIMA(p,q,d) includes the process of difference on the basis of ARMA(p,q). Therefore, ARIMA can handle non-stationary time series, but it can't handle periodic series well. Therefore, SARIMA(p,q,d,P,Q,D,s) expands on the basis of ARIMA(p,q,d) and adds three hyperparameters of P Q D and a seasonal cycle parameter s. Time series data with seasonal components can be supported. 5 | ## Use scenario 6 | SARIMA is suitable for time series data with seasonal variation , and the data volume is larger , and the effect of the model with too little data is poor. 7 | 8 | ## Algorithm principle 9 | SARIMA consists of four parts: seasonal correlation (S), autoregression (AR), difference (I), and average shift (MA) : 10 | 11 | (1) **AR (autoregressive) part ** indicates the dependency between the current value and the past value, that is, there is a linear relationship between the current value and the value of several past time points, and the appropriate lag order can be determined through PACF, corresponding to the parameter p; 12 | 13 | (2) **I (difference) part ** is to eliminate the non-stationarity of the data. Through differential processing of the time series data, the non-stationary time series data can be transformed into stable time series data, corresponding to parameter d; 14 | 15 | (3) **MA (moving average) part ** represents the dependence between the current value and the observed errors at several past time points, and the appropriate lag order can be determined by ACF, corresponding to parameter q; 16 | 17 | (4) **S (seasonal term) ** includes four parts: seasonal regression (SAR), seasonal difference (SI), seasonal moving average (SMA) and seasonal frequency (s), corresponding to parameters P, D, Q and s respectively. The first three seasonal terms have similar effects to their counterparts in the ARIMA model. 18 | 19 | In summary, the SARIMA model uses techniques such as autoregression, difference, and moving average, and takes into account seasonal correlation terms, to predict time series data with seasonality and trend. -------------------------------------------------------------------------------- /site/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | OpsPilot is an open source intelligent operation and maintenance assistant based on cutting-edge artificial intelligence technology from the WeOps team. It uses advanced machine learning, deep learning and cutting-edge large model capabilities as AI capabilities, and supports rich operation and maintenance integration capabilities to provide intelligent operation and maintenance services 4 | 5 | ![architecture diagram](https://static.cwoa.net/01adc49936ae41d68dded993461a7dd0.jpg) 6 | 7 | OpsPilot includes three main capabilities: 8 | 9 | > * Powerful private domain knowledge Q&A 10 | > * Efficient ChatOps 11 | > * Insightful intelligent guidance 12 | 13 | Product highlights: 14 | 15 | > * Multi-channel connection with users 16 | > * Rich AIOPS model 17 | > * Comprehensive data integration capabilities 18 | 19 | ## Core concept 20 | 21 | In OpsPilot, there are the following core concepts: 22 | 23 | * **Robot** : Every robot is a Pilot. The Pilot is scheduled by K8S to contact the user through the channel 24 | * **AI model** : AI model provides AI skills for the Pilot, it can be simply said that the expansion pack tells the Pilot what actions can be done, AI model provides magic for actions 😁. AI models can also provide services directly to the outside world 25 | Integration: Integration is how Pilot interacts with external systems, including K8S, Jenkins, Gitlab, WeOps Lite, and more 26 | * **Channel** : Channel is the channel for Pilot to connect with users, including Dingding, Web, enterprise wechat 27 | * **Knowledge Base** : Knowledge base provides RAG support for robots, so that robots can recover private domain knowledge 28 | 29 | ## Explicit knowledge & Implicit knowledge 30 | 31 | **Explicit knowledge** : We believe that in the operation and maintenance system, all directly expressed, such as CMDB asset association, alarm information, indicator information, etc., are explicit knowledge 32 | 33 | **Tacit knowledge**: We believe that in the operation and maintenance system, everything that needs to be obtained through reasoning, calculation, prediction and other ways, such as root cause analysis, predictive alarm, etc., through the AIOPS algorithm to extract and analyze the explicit knowledge, uniformly called tacit knowledge 34 | 35 | ## Intelligent guidance 36 | 37 | OpsPilot has not yet positioned itself as a Virtual SRE, and we believe that at this stage, the reliability of letting large models play too much subjective initiative in the field of operation and maintenance is not high. Therefore, we are more inclined to combine the advantages of task-based robots and conversational robots to guide users to complete operation and maintenance tasks step by step, or analyze the root causes of alarms -------------------------------------------------------------------------------- /site/features/knowledges.md: -------------------------------------------------------------------------------- 1 | # 知识管理 2 | 3 | 知识管理模块提供了对知识库的管理,支持用户上传文件型知识、人工录入的知识、URL爬取的知识。知识上传到知识库被训练之后,有两种主要的使用途径: 4 | 5 | 1. 为Pilot提供知识,消除大模型由于数据的时效性、准确性等原因产生的幻觉问题。可以认为我们给智能运维助理装载了私域知识,让它执行技能的时候能够更加符合我们的期望 6 | 2. 为外部应用提供混合检索+ReRank的能力。有些时候,第三方应用仅仅只需要使用混合知识检索,典型的场景是告警推荐,这个时候第三方应用并不需要使用Pilot那么丰富的能力,它只是希望能够通过告警检索最佳的匹配方案,并且能够预览原文 7 | 8 | ## 知识库 9 | 10 | 知识库是知识的聚合,由多个种类的知识聚合而成,并且利用各种算法提升知识索引的准确性。在知识库管理的过程,我们主要关注以下几个方面: 11 | 12 | * 哪些知识组成了这个知识库 13 | * 如何使用混合检索+ReRank,让检索变得更加准确 14 | * 混合搜索的时候,语义检索和文本检索的权重是如何分配的 15 | * 对知识使用怎么样的分块模式 16 | 17 | 总的来说,我们会在知识库这里对知识加工进行精细化的配置,以供LLM技能使用。 18 | 19 | ![知识1.png](https://static.cwoa.net/785762b0748349fcac9d5385586ddca2.png) 20 | 21 | 如下图,在知识库需要选择使用的模型等参数,具体说明如下 22 | * 基本信息:包括知识库的名称、描述 23 | * Embeding模型:选择用于知识库构建和检索的Embed模型,提供了内置的四类Embed模型,可根据任务和需求选择合适的模型。 24 | * 分块解析:设置分块解析的参数,包括分块大小和分块重叠。将输入文本分成多个块,并指定块的大小和重叠部分,以便更好地处理长文本。 25 | * 语义分块解析:选择使用Embed模型进行语义分块解析。这可以帮助机器人更好地理解和处理输入文本,并将其分解为不同的语义块。 26 | * 文本检索:设置文本检索的权重。可以为知识库中的不同文本部分设置不同的权重,以影响检索结果的排序和相关性。 27 | * 向量检索:设置向量检索的参数,包括检索权重、返回数量和候选数量。通过调整这些参数,可以控制向量检索的影响力、返回结果的数量以及候选结果的数量。 28 | * 结果重排序:选择Rerank模型和返回结果的数量。通过启用Rerank模型并设置结果数量,可以对检索到的结果进行再排序,从而提供更准确和相关的答案。 29 | * 知识:可以使用`文件知识`、`手工录入`、`网页知识`三类知识 30 | 31 | ![知识1-1.png](https://static.cwoa.net/cf8285e7f1a24bc6a237750f343ea69c.png) 32 | 33 | ![知识1-2.png](https://static.cwoa.net/f083663b1f034f4fa12771f8553b46ae.png) 34 | 35 | ![知识1-3.png](https://static.cwoa.net/284c3cca77754984b4b551fbb35b26e3.png) 36 | 37 | ## 知识 38 | 39 | OpsPilot能够管理知识,包括 `文件知识`、`手工录入`、`网页知识`,并供知识库使用。 40 | 41 | ### 文本知识 42 | 43 | 在日常运维过程中,会产生多种类型的知识,他们一般会以文件类型存在,这也是OpsPilot知识库中最主要的私域知识来源。OpsPilot支持对以下知识进行知识解析 44 | 45 | * Markdown 46 | * Word 47 | * Excel 48 | * CSV 49 | * PPT 50 | * TXT 51 | 52 | ![知识2.png](https://static.cwoa.net/433dca6382d94445ac965e54aa63d1e4.png) 53 | 54 | ### 手工录入 55 | 56 | * 运维脚本的代码段、零散的碎片知识,都适合用手工录入的方式形成知识,让OpsPilot能够对其进行使用 57 | 58 | ![知识3.png](https://static.cwoa.net/53b66500fc65457b8afe6b6b1fb767b9.png) 59 | 60 | ### 网页知识 61 | 62 | 互联网上有非常多有用的知识,例如RabbitMQ的官方文档、Redis的官方文档,这些软件会因为对应版本的不一样,具备不一样的特性,或者具备不一样的命令行参数,这种时候我们可以使用网页知识,对他们进行快速、持续的知识捕获 63 | 64 | ![知识4.png](https://static.cwoa.net/913fe9c790a74f969828b3344ededb96.png) 65 | 66 | ## API 67 | 68 | ### 知识检索 69 | 70 | > POST /api/knowledge_search/search/ 71 | 72 | ``` 73 | { 74 | "knowledgebase_folder_ids": [ 75 | 1 76 | ], 77 | "query": "能监控Linux吗", 78 | "score_threshold": 0.7, 79 | "metadata":{ 80 | "doc_type":"text" 81 | } 82 | } 83 | ``` 84 | 85 | 参数说明 86 | 87 | | 变量 | 描述 | 88 | | ------------------------ | -------------------------------- | 89 | | knowledgebase_folder_ids | 知识库的ID号数组 | 90 | | query | 搜索语句 | 91 | | score_threshold | 过滤阈值 | 92 | | metadata | 知识库元数据过滤条件字典,可不填 | 93 | 94 | ``` 95 | score_threshold 96 | ``` 97 | -------------------------------------------------------------------------------- /site/api/aiops/causation/causality.md: -------------------------------------------------------------------------------- 1 | # causality 2 | 3 | ## Algorithm introduction 4 | 5 | A probabilistic causal model is a framework for dealing with causality that uses probability distributions to describe the causal relationship between variables. The causality library used in this paper implements the Inductive Causation with latent variables (IC) algorithm, which is an inference method based on directed graph. The causal relationship between variables is inferred by observing the conditional independence relationship between them. The IC algorithm constructs a graph model by testing the conditional independence of the raw data, where each node represents a variable and the directed edge represents the causal relationship between the variables. The algorithm first constructs a complete directed graph, then gradually reduces unnecessary edges through a series of recursive rules, and finally gets a reasonable causal graph model. 6 | 7 | ## Use scenario 8 | 9 | This algorithm is suitable for causal inference of 'discrete' data 10 | 11 | ## Algorithm principle 12 | 13 | The core idea of the algorithm is to use the conditional independence relation to infer causality through the statistical characteristics of the observed data. It can deal with issues such as latent variables and selective omissions, and is able to make inferences in complex networks of causation. The specific process is as follows: 14 | 15 | (1) Data preparation: discrete data, such as four nodes A, B, C and D, node A appears as 1, and node a does not appear as 0; 16 | 17 | (2) Build a complete graph: Build a directed complete graph where each node has a directed edge link with other nodes; 18 | 19 | (3) Conditional independence test: For each pair of variables in the figure, conditional independence test is carried out to determine whether causality exists; 20 | 21 | (4) Recursion: Based on the results of the conditional independence test, a series of recursive rules are applied to gradually reduce the edges in the graph. Recursive rules include: (1) If variable A and variable B are conditionally independent, and variable B is conditionally independent from variable C, then it can be inferred that there is no direct causal relationship between variable A and variable C, and the edge between A and C is removed; (2) If variable A is conditionally independent of variable B, and variable C is A common neighbor of A and B (that is, has an edge connection with both A and B), then A common causal relationship between variables A and B can be inferred, and an edge is added between A and B; 22 | 23 | (5) Determine the direction of the directed edge: Determine the direction of the directed edge by observing the order in which the variable is operated during the recursive rule process. If an edge is added to a variable and then removed or replaced multiple times, then the edge can confirm the direction; 24 | 25 | (6) Get the final causal graph: After processing by recursive rules, the resulting graph is the final causal graph, representing the causal relationship between variables. -------------------------------------------------------------------------------- /site/features/ai_models.md: -------------------------------------------------------------------------------- 1 | # AI模型 2 | 3 | 在AI模型功能块,可以对OpsPilot能够使用的AI技能进行管理,包括配置AI能力的通道配置,技能配置 4 | 5 | ## Embed模型 6 | 7 | Embed模型为知识提供向量化的能力,是知识库能够进行语义检索的支撑功能,OpsPilot内置以下Embed模型,内置的这些模块可以在“知识管理-知识”中进行使用。 8 | 9 | ![模型1.png](https://static.cwoa.net/63fca4df4b93470d991944a39573e05a.png) 10 | 11 | Embed模型支持新增/编辑和删除等操作,新增模型时需要选择类型(langserver类型是用于使用Embed模型进行语言处理任务的服务类型,可以通过不同的API(如HTTP的RESTful API、GRPC、WebSocket)与服务器进行交互,OpenAI类型是指OpenAI GPT模型的服务类型,通过OpenAI API可与OpenAI服务器进行交互,并使用GPT模型进行自然语言处理任务。)和配置信息(比如基本url) 12 | 13 | ![模型1-1.png](https://static.cwoa.net/8810c79527b643ef930251d41e57884b.png) 14 | 15 | ## ReRank模型 16 | 17 | ReRank模型可以对检索出来的知识进行重排序,让大模型在使用RAG能力的时候,知识检索效果更好。 18 | 19 | OpsPilot内置以下ReRank模型,内置的这些模块可以在“知识管理-知识”中进行使用。 20 | 21 | 22 | ![模型2.png](https://static.cwoa.net/1d101b079b8a4c13ad49ba55e0bade60.png) 23 | 24 | ReRank模型支持新增/编辑和删除等操作,新增模型时需要选择类型(langserver类型是允许开发人员通过标准化API与服务器交互,以使用Rerank模型进行语言处理任务的服务)和配置信息(比如基本url) 25 | 26 | ![模型2-2.png](https://static.cwoa.net/b3a5b63566fe4dec8410543df7ebfb2a.png) 27 | 28 | ## LLM模型 29 | 30 | LLM模型用于配置模型的基础配置,如凭据,方便后续的LLM技能所使用,OpsPilot内置以下LLM模型的支持: 31 | 32 | * OpenAI 33 | * GPT-3.5-Turbo-16K 34 | * GPT-4-32K 35 | 36 | ![模型3.png](https://static.cwoa.net/fc7cd10259584a74a3478021e25d169a.png) 37 | 38 | LLM模型支持新增/编辑和删除等操作,新增模型时需要选择类型(比如ChatGPT)和配置信息(比如model、OpenAI API所需的API密钥、与OpenAI API进行交互的服务器地址、生成文本时控制多样性的参数数值较低会使结果更保守和一致,而数值较高会使结果更多样化。) 39 | 40 | ![模型3-3.png](https://static.cwoa.net/3cfdffb027394a30a55c32717c856605.png) 41 | 42 | ## LLM技能 43 | 44 | 在OpsPilot里面,大模型对应的是LLM技能 45 | 46 | > 为什么不是角色?因为在OpsPilot里面,Pilot才是真正的机器人,是OpsPilot的核心,LLM只是作为一个一个的技能,供Pilot执行动作的时候使用 47 | 48 | LLM技能有如下可用的模板变量: 49 | 50 | * input:用户输入的内容 51 | * chat_history:聊天历史,在启用对话增强的使用会被自动填充 52 | 53 | ![模型4.png](https://static.cwoa.net/23bf0d66d9984cdcbcbfb7f60ba675df.png) 54 | 55 | LLM技能创建完成后,可以被机器人所使用。 56 | 57 | OpsPilot为每个Pilot的核心扩展包内置了以下技能: 58 | 59 | * 开放知识问答:用于与用户进行开放型对话,让Pilot具备对话型机器人的能力。注意!技能ID必须为 `action_llm_fallback`,Pilot在不清楚应该执行什么任务的时候,会fallback到这个技能。该技能可调整如下参数 60 | * LLM模型:指定要使用的LLM模型版本,如"gpt-4-32k"。这决定了LLM技能使用的基础语言生成模型。 61 | * 技能提示词:为了更好地引导LLM技能生成相关的回复,可以提供技能提示词。这些提示词可以是一些关键词、短语或句子,有助于模型理解预期的回复内容。 62 | * 对话增强:对话增强功能用于处理对话历史和设置对话窗口大小。对话历史是指将过去的对话文本提供给模型,以便它能够更好地理解上下文。对话窗口大小指定了对话历史的文本数量或长度。 63 | * 知识库:启用RAG(Retrieve and Generate)知识库功能。RAG模型结合了信息检索和语言生成,以生成更具信息量和相关性的回复。配置知识库会涉及指定RAG模型以及相关参数,如显示RAG知识来源和RAG分数阈值(RAG分数阈值是设定的一个限制值,用于筛选出高于该阈值的知识片段,只有分数高于阈值的片段,才会被用于生成回复,以控制生成回复的质量和相关性。)。 64 | 65 | ![模型4-4.png](https://static.cwoa.net/710cea7cf66d4a4e88afcb06a951a475.png) 66 | 67 | 68 | ## API 69 | 70 | ### 文本向量化 71 | 72 | > POST /api/embed/embed_content/ 73 | 74 | ``` 75 | { 76 | "embed_model_id": 1, 77 | "content": "介绍一下你的团队" 78 | } 79 | ``` 80 | 81 | ### 内容重排序 82 | 83 | > POST /api/rerank/rerank_sentences/ 84 | 85 | ``` 86 | { 87 | "rerank_id": 1, 88 | "query": "介绍一下Rasa", 89 | "top_k": 2, 90 | "sentences": [ 91 | "今天天气真好", 92 | "Rasa是什么", 93 | "Django和Rasa怎么结合起来用" 94 | ] 95 | } 96 | ``` 97 | 98 | ### 执行LLM技能 99 | 100 | > POST /api/llm/execute/ 101 | 102 | ``` 103 | { 104 | "llm_skill_id": 1, 105 | "user_message": "介绍一下你们团队的开发模式", 106 | "chat_history": [{"event":"user","text":"hello"},{"event":"bot","text":"hi"}], 107 | "super_system_prompt": "" 108 | } 109 | ``` 110 | -------------------------------------------------------------------------------- /site/api/bionics.md: -------------------------------------------------------------------------------- 1 | The bionics service provides the ability to generate png images from JavaScript configurations and supports EChart charts 2 | 3 | 4 | ## Generate EChart Image 5 | 6 | ### Python Example 7 | ```python 8 | import requests 9 | import base64 10 | 11 | url = 'http://bionics.ops-pilot/echart/generate' 12 | 13 | options = { 14 | "options": { 15 | "xAxis": { 16 | "type": "category", 17 | "boundaryGap": False, 18 | "data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] 19 | }, 20 | "yAxis": { 21 | "type": "value" 22 | }, 23 | "series": [ 24 | { 25 | "data": [820, 932, 901, 934, 1290, 1330, 1320], 26 | "type": "line", 27 | "areaStyle": {} 28 | } 29 | ] 30 | }, 31 | "width": 500, 32 | "height": 200, 33 | "theme": "westeros", 34 | "fontSize": 12, 35 | "mode": "base64" 36 | } 37 | 38 | response = requests.post(url, json=options) 39 | 40 | 41 | if response.status_code == 200: 42 | 43 | image_data_base64 = response.text.replace("data:image/png;base64,", "") 44 | 45 | image_data = base64.b64decode(image_data_base64) 46 | 47 | with open("generated_chart.png", "wb") as image_file: 48 | image_file.write(image_data) 49 | 50 | print("Image successfully saved to 'generated_chart.png'") 51 | else: 52 | print(f"Failed to generate image. Status code: {response.status_code}") 53 | print(f"Response: {response.text}") 54 | 55 | ``` 56 | 57 | ### Rest API 58 | 59 | ```bash 60 | curl --location --request POST --X POST 'http://bionics.ops-pilot/echart/generate' \ 61 | --header 'Content-Type: application/json' \ 62 | --data '{ 63 | "options":{ 64 | "xAxis": { 65 | "type": "category", 66 | "boundaryGap": false, 67 | "data": [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" ] 68 | }, 69 | "yAxis": { 70 | "type": "value" 71 | }, 72 | "series": [ 73 | { 74 | "data": [ 820, 932, 901, 934, 1290, 1330, 1320 ], 75 | "type": "line", 76 | "areaStyle": {} 77 | } 78 | ] 79 | } 80 | }' 81 | ``` 82 | | Parameter | Description | Mandatory | Default value | Remarks | 83 | | ----------- | ---------------------------- | --------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 84 | | The options | Echart chart Options | is | | 85 | | width | Canvas width | No | 500 | speed at which the Canvas size will be generated | 86 | | height | Canvas height | no | 200 | Canvas size speed at which the canvas will be generated | 87 | | theme | Echart's theme | no | westeros | | 88 | | fontSize | Canvas font size | no | 12 | | 89 | | mode | The returned image format is | no | base64 | The optional base64/stream. In Base64 mode, the image is encoded as Base64 and returned to the caller; in Stream mode, the image is returned directly in stream mode | -------------------------------------------------------------------------------- /site/.vitepress/config.mts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitepress'; 2 | 3 | // https://vitepress.dev/reference/site-config 4 | export default defineConfig({ 5 | title: 'OpsPilot', 6 | description: 'OpsPilot Site', 7 | themeConfig: { 8 | search: { 9 | provider: 'local', 10 | }, 11 | 12 | // https://vitepress.dev/reference/default-theme-config 13 | nav: [ 14 | { text: 'Home', link: '/' }, 15 | { text: 'Doc', link: '/introduction' }, 16 | { text: '|', link: '#' }, 17 | { text: 'WeOps', link: 'https://wedoc.canway.net/' }, 18 | ], 19 | 20 | sidebar: [ 21 | { 22 | text: 'Document', 23 | items: [ 24 | { text: 'Introduction', link: '/introduction' }, 25 | { text: 'Quick Start', link: '/quick-start' }, 26 | { 27 | text: 'API', 28 | items: [ 29 | { text: 'RAG Server', link: '/api/rag_server' }, 30 | { text: 'Chunk Server', link: '/api/chunk_server' }, 31 | { text: 'Pandoc Server', link: '/api/pandoc_server' }, 32 | { text: 'OCR Server', link: '/api/ocr_server' }, 33 | { text: 'Fast Embed Server', link: '/api/fast_embed_server' }, 34 | { text: 'BCE Embed Server', link: '/api/bce_embed_server' }, 35 | { text: 'Chat Server', link: '/api/chat_server' }, 36 | { text: 'Bionics', link: '/api/bionics' }, 37 | { text: 'SaltStack Server', link: '/api/saltstack_server' }, 38 | { 39 | text: 'Classicfy AIOPS Server', 40 | link: '/api/classicfy_aiops_server', 41 | items: [ 42 | { 43 | text: 'Anomaly Detection', 44 | items: [ 45 | { 46 | text: 'ABOD', 47 | link: '/api/aiops/anomaly/abod', 48 | }, 49 | { 50 | text: 'ECOD', 51 | link: '/api/aiops/anomaly/ecod', 52 | }, 53 | { 54 | text: 'IForest', 55 | link: '/api/aiops/anomaly/iforest', 56 | }, 57 | { 58 | text: 'INNE', 59 | link: '/api/aiops/anomaly/inne', 60 | }, 61 | { 62 | text: 'KNN', 63 | link: '/api/aiops/anomaly/knn', 64 | }, 65 | { 66 | text: 'KPCA', 67 | link: '/api/aiops/anomaly/kpca', 68 | }, 69 | { 70 | text: 'MAD', 71 | link: '/api/aiops/anomaly/mad', 72 | }, 73 | { 74 | text: 'OneClassSVM', 75 | link: '/api/aiops/anomaly/oneclasssvm', 76 | }, 77 | { 78 | text: 'SUOD', 79 | link: '/api/aiops/anomaly/suod', 80 | }, 81 | { 82 | text: 'XGBOD', 83 | link: '/api/aiops/anomaly/xgbod', 84 | }, 85 | ], 86 | }, 87 | { 88 | text: 'Causal Analysis', 89 | items: [ 90 | { 91 | text: 'FPGrowth', 92 | link: '/api/aiops/causation/fpgrowth', 93 | }, 94 | { 95 | text: 'Causality', 96 | link: '/api/aiops/causation/causality', 97 | }, 98 | ], 99 | }, 100 | { 101 | text: 'Pattern Discovery', 102 | items: [ 103 | { 104 | text: 'Drain3', 105 | link: '/api/aiops/logreduce/drain3', 106 | }, 107 | ], 108 | }, 109 | { 110 | text: 'Timeseries Prediction', 111 | items: [ 112 | { 113 | text: 'SARIMA', 114 | link: '/api/aiops/timeseries/sarima', 115 | }, 116 | { 117 | text: 'Holt-Winter', 118 | link: '/api/aiops/timeseries/holtwinter', 119 | }, 120 | ], 121 | }, 122 | ], 123 | }, 124 | ], 125 | }, 126 | ], 127 | }, 128 | ], 129 | 130 | socialLinks: [ 131 | { icon: 'github', link: 'https://github.com/WeOps-Lab/OpsPilot' }, 132 | ], 133 | }, 134 | }); 135 | -------------------------------------------------------------------------------- /site/api/chat_server.md: -------------------------------------------------------------------------------- 1 | The chat server provides the ability to interact with the LLM, including single-round chat, multi-round chat, and multi agent 2 | 3 | 4 | ## OpenAI Chat 5 | 6 | ### LangServer API 7 | 8 | ``` 9 | chat_server = RemoteRunnable(f'{CHAT_SERVICE_URL}/openai') 10 | result = chat_server.invoke({ 11 | "system_message_prompt": "", 12 | "openai_api_base": "", 13 | "openai_api_key": "", 14 | "temperature": 0.7, 15 | "model": "gpt-3.5-turbo", 16 | "user_message": "", 17 | "chat_history": [ 18 | { 19 | "event":"bot", 20 | "text":"" 21 | }, 22 | { 23 | "event":"user", 24 | "text":"" 25 | } 26 | ], 27 | "conversation_window_size": 6, 28 | "rag_context": "", 29 | }) 30 | ``` 31 | 32 | | param | desc | 33 | | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | 34 | | system_message_prompt | The prompt to be used to generate the system message | 35 | | openai_api_base | The base URL for the OpenAI API | 36 | | openai_api_key | The API key for the OpenAI API | 37 | | temperature | The temperature to be used for the OpenAI API | 38 | | model | The model to be used for the OpenAI API | 39 | | user_message | The message from the user | 40 | | chat_history | The chat history | 41 | | conversation_window_size | The size of the conversation window | 42 | | rag_context | background on the use of LLM | 43 | | tools | when given tools,the chat server will change to llm agent mode,tools is a list of tools that the agent can use,for example ["shell","duckduckgo-search"] | 44 | 45 | 46 | ## Zhipu Chat 47 | ### LangServer API 48 | 49 | ``` 50 | chat_server = RemoteRunnable(f'{CHAT_SERVICE_URL}/zhipu') 51 | result = chat_server.invoke({ 52 | "system_message_prompt": "", 53 | "api_base": "", 54 | "api_key": "", 55 | "temperature": 0.7, 56 | "model": "glm-4", 57 | "user_message": "", 58 | "chat_history": [ 59 | { 60 | "event":"bot", 61 | "text":"" 62 | }, 63 | { 64 | "event":"user", 65 | "text":"" 66 | } 67 | ], 68 | "conversation_window_size": 6, 69 | "rag_context": "", 70 | }) 71 | ``` 72 | 73 | | param | desc | 74 | | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | 75 | | system_message_prompt | The prompt to be used to generate the system message | 76 | | api_base | The base URL for the Zhipu API | 77 | | api_key | The API key for the Zhipu API | 78 | | temperature | The temperature to be used for the Zhipu API | 79 | | model | The model to be used for the Zhipu API | 80 | | user_message | The message from the user | 81 | | chat_history | The chat history | 82 | | conversation_window_size | The size of the conversation window | 83 | | rag_context | background on the use of LLM | 84 | | tools | when given tools,the chat server will change to llm agent mode,tools is a list of tools that the agent can use,for example ["shell","duckduckgo-search"] | 85 | ``` 86 | 87 | 88 | -------------------------------------------------------------------------------- /site/api/chunk_server.md: -------------------------------------------------------------------------------- 1 | Chunk-Server is responsible for knowledge partitioning, supports semantic and length partitioning of files, and has a variety of knowledge partitioning options 2 | 3 | ## File Partitioning 4 | 5 | ### LangServe API 6 | 7 | ```python 8 | file_remote = RemoteRunnable(FILE_CHUNK_SERIVCE_URL) 9 | remote_docs = file_remote.invoke( 10 | { 11 | "enable_recursive_chunk_parse": true 12 | "recursive_chunk_size": 128, 13 | "recursive_chunk_overlap": 0, 14 | "enable_semantic_chunck_parse": false, 15 | "enable_ocr_parse": false, 16 | "ocr_provider_address": "", 17 | "semantic_embedding_address": "", 18 | "excel_header_row_parse": false, 19 | "excel_full_content_parse": true, 20 | "file_name": "", 21 | "file": ""#base46 file string, 22 | "custom_metadata": { 23 | "knowledge_type": "file", 24 | "knowledge_id": 1, 25 | "knowledge_title": "", 26 | "knowledge_folder_id": 1, 27 | **knowledge.custom_metadata, 28 | }, 29 | } 30 | ) 31 | ``` 32 | 33 | ### Rest API 34 | 35 | #### Request 36 | 37 | POST: `file_chunk/invode` 38 | 39 | ``` 40 | { 41 | "input":{ 42 | "enable_recursive_chunk_parse": flase, 43 | "recursive_chunk_size": 128, 44 | "recursive_chunk_overlap": 0, 45 | "enable_semantic_chunck_parse": false, 46 | "semantic_embedding_address": "http://fast-embed-server.ops-pilot", 47 | "ocr_provider_address": "http://ocr-server.ops-pilot", 48 | "enable_ocr_parse": false, 49 | "excel_header_row_parse": false, 50 | "excel_full_content_parse": false, 51 | "custom_metadata": { 52 | 53 | }, 54 | "file": "", 55 | "file_name": "" 56 | } 57 | } 58 | ``` 59 | 60 | | param | desc | 61 | | ---------------------------- | ---------------------------- | 62 | | enable_recursive_chunk_parse | Enable recursive chunk parse | 63 | | recursive_chunk_size | Recursive chunk size | 64 | | recursive_chunk_overlap | Recursive chunk overlap | 65 | | enable_semantic_chunck_parse | Enable semantic chunk parse | 66 | | semantic_embedding_address | Semantic embedding address | 67 | | ocr_provider_address | OCR provider address | 68 | | enable_ocr_parse | Enable OCR parse | 69 | | excel_header_row_parse | Excel header row parse | 70 | | excel_full_content_parse | Excel full content parse | 71 | | custom_metadata | Custom metadata | 72 | | file | File to parse,base64 string | 73 | | file_name | File name | 74 | 75 | #### Response 76 | 77 | ``` 78 | { 79 | "output":[ 80 | { 81 | "id":"", 82 | "metadata":{ 83 | "format":"table", // image 84 | }, 85 | "page_content":"", 86 | "type":"Document" 87 | } 88 | ] 89 | } 90 | ``` 91 | 92 | ## Web Page Scraping And Parsing 93 | 94 | ### LangServe API 95 | 96 | ```python 97 | web_page_remote = RemoteRunnable(WEB_PAGE_CHUNK_SERVICE_URL) 98 | remote_docs = web_page_remote.invoke( 99 | { 100 | "enable_recursive_chunk_parse": true 101 | "recursive_chunk_size": 256, 102 | "recursive_chunk_overlap": 0, 103 | "enable_semantic_chunck_parse": false, 104 | "semantic_embedding_address": "", 105 | "url": "", 106 | "max_depth": 1, 107 | "custom_metadata": { 108 | "knowledge_type": "webpage", 109 | "knowledge_id": knowledge.id, 110 | "knowledge_title": knowledge.title, 111 | "knowledge_folder_id": knowledge.knowledge_base_folder.id, 112 | **knowledge.custom_metadata, 113 | }, 114 | } 115 | ) 116 | ``` 117 | 118 | ### Rest API 119 | 120 | #### Request 121 | 122 | POST: `webpage_chunk/invoke` 123 | 124 | ``` 125 | { 126 | "input":{ 127 | "enable_recursive_chunk_parse": false, 128 | "recursive_chunk_size": 128, 129 | "recursive_chunk_overlap": 0, 130 | "enable_semantic_chunck_parse": false, 131 | "semantic_embedding_address": "http://fast-embed-server.ops-pilot", 132 | "ocr_provider_address": "http://ocr-server.ops-pilot", 133 | "enable_ocr_parse": false, 134 | "excel_header_row_parse": false, 135 | "excel_full_content_parse": false, 136 | "custom_metadata": { 137 | 138 | }, 139 | "url": "", 140 | "max_depth": 1, 141 | } 142 | } 143 | ``` 144 | 145 | | param | desc | 146 | | ---------------------------- | ---------------------------- | 147 | | enable_recursive_chunk_parse | Enable recursive chunk parse | 148 | | recursive_chunk_size | Recursive chunk size | 149 | | recursive_chunk_overlap | Recursive chunk overlap | 150 | | enable_semantic_chunck_parse | Enable semantic chunk parse | 151 | | semantic_embedding_address | Semantic embedding address | 152 | | ocr_provider_address | OCR provider address | 153 | | enable_ocr_parse | Enable OCR parse | 154 | | excel_header_row_parse | Excel header row parse | 155 | | excel_full_content_parse | Excel full content parse | 156 | | custom_metadata | Custom metadata | 157 | | url | URL to parse | 158 | | max_depth | Max depth to parse | 159 | 160 | #### Response 161 | 162 | ``` 163 | { 164 | "output":[ 165 | { 166 | "id":"", 167 | "metadata":{ 168 | "format":"table", // image 169 | }, 170 | "page_content":"", 171 | "type":"Document" 172 | } 173 | ] 174 | } 175 | ``` 176 | 177 | ## Manual Content Parsing 178 | 179 | ### LangServe API 180 | ```python 181 | manual_remote = RemoteRunnable(MANUAL_CHUNK_SERVICE_URL) 182 | remote_docs = manual_remote.invoke( 183 | { 184 | "enable_recursive_chunk_parse": true, 185 | "recursive_chunk_size": 256, 186 | "recursive_chunk_overlap": 0, 187 | "enable_semantic_chunck_parse": false, 188 | "semantic_embedding_address": "", 189 | "content": "", 190 | "custom_metadata": { 191 | "knowledge_type": "manual", 192 | "knowledge_id": knowledge.id, 193 | "knowledge_title": knowledge.title, 194 | "knowledge_folder_id": knowledge.knowledge_base_folder.id, 195 | **knowledge.custom_metadata, 196 | }, 197 | } 198 | ) 199 | 200 | ``` 201 | ### Rest API 202 | 203 | #### Request 204 | 205 | POST: `manual_chunk/invoke` 206 | ``` 207 | { 208 | "input":{ 209 | "enable_recursive_chunk_parse": false, 210 | "recursive_chunk_size": 128, 211 | "recursive_chunk_overlap": 0, 212 | "enable_semantic_chunck_parse": false, 213 | "semantic_embedding_address": "http://fast-embed-server.ops-pilot", 214 | "ocr_provider_address": "http://ocr-server.ops-pilot", 215 | "enable_ocr_parse": false, 216 | "excel_header_row_parse": false, 217 | "excel_full_content_parse": false, 218 | "custom_metadata": { 219 | 220 | }, 221 | "content": "" 222 | } 223 | } 224 | ``` 225 | 226 | | param | desc | 227 | | ---------------------------- | ---------------------------- | 228 | | enable_recursive_chunk_parse | Enable recursive chunk parse | 229 | | recursive_chunk_size | Recursive chunk size | 230 | | recursive_chunk_overlap | Recursive chunk overlap | 231 | | enable_semantic_chunck_parse | Enable semantic chunk parse | 232 | | semantic_embedding_address | Semantic embedding address | 233 | | ocr_provider_address | OCR provider address | 234 | | enable_ocr_parse | Enable OCR parse | 235 | | excel_header_row_parse | Excel header row parse | 236 | | excel_full_content_parse | Excel full content parse | 237 | | custom_metadata | Custom metadata | 238 | | content | Content to parse | 239 | 240 | #### Response 241 | 242 | ``` 243 | { 244 | "output":[ 245 | { 246 | "id":"", 247 | "metadata":{ 248 | "format":"table", // image 249 | }, 250 | "page_content":"", 251 | "type":"Document" 252 | } 253 | ] 254 | } 255 | ``` 256 | -------------------------------------------------------------------------------- /site/api/rag_server.md: -------------------------------------------------------------------------------- 1 | RAG Server is a knowledge management module in OpsPilot, which is responsible for knowledge indexing and retrieval. 2 | 3 | ## Elasticsearch Document Index 4 | 5 | ### LangServe API 6 | 7 | ```python 8 | remote_indexer = RemoteRunnable(RAG_SERVER_URL) 9 | 10 | knowledge_docs=[] #here is a Document list 11 | remote_indexer.invoke( 12 | { 13 | "elasticsearch_url": ELASTICSEARCH_URL, 14 | "elasticsearch_password": ELASTICSEARCH_PASSWORD, 15 | "embed_model_address": "", 16 | "index_name": index_name, 17 | "index_mode": "overwrite", 18 | "docs": knowledge_docs, 19 | } 20 | ) 21 | ``` 22 | 23 | ### Rest API 24 | 25 | 26 | #### Request 27 | POST: `/elasticsearch_index/invoke` 28 | 29 | ``` 30 | { 31 | "input":{ 32 | "elasticsearch_url":"", 33 | "elasticsearch_password":"", 34 | "embed_model_address":"", 35 | "index_name":"", 36 | "index_mode":"", 37 | "chunk_size":100, 38 | "max_chunk_bytes":1000000, 39 | "docs":[ 40 | { 41 | "id":"", 42 | "metadata":{ 43 | "knowledge_type":"", 44 | "knowledge_id":1, 45 | "knowledge_title":"", 46 | "knowledge_folder_id":1, 47 | #custom metadata 48 | }, 49 | "page_content":"" 50 | } 51 | ] 52 | } 53 | } 54 | ``` 55 | 56 | | param | desc | 57 | | ---------------------- | ------------------------------------------ | 58 | | elasticsearch_url | ElasticSearch URL | 59 | | elasticsearch_password | ElasticSearch password | 60 | | embed_model_address | Embedding model address ,for vector search | 61 | | index_name | ElasticSearch index name | 62 | | index_mode | Index mode,`overwrite` or `append` | 63 | | chunk_size | Chunk size for indexing | 64 | | max_chunk_bytes | Max chunk bytes for indexing | 65 | | docs | Documents to index | 66 | 67 | #### Response 68 | 69 | ``` 70 | { 71 | "output": true 72 | } 73 | ``` 74 | 75 | ## Delete Elasticsearch Index 76 | 77 | some times we need to delete hole index or some documents in the index 78 | 79 | ### LangServe API 80 | 81 | ```python 82 | remote_indexer = RemoteRunnable(RAG_SERVER_URL) 83 | 84 | result=remote_indexer.invoke( 85 | { 86 | "elasticsearch_url": ELASTICSEARCH_URL, 87 | "elasticsearch_password": ELASTICSEARCH_PASSWORD, 88 | "index_name": index_name, 89 | "mode": "delete_index", 90 | "metadata_filter": { 91 | 92 | }, 93 | } 94 | ) 95 | ``` 96 | 97 | ### Rest API 98 | 99 | #### Request 100 | 101 | POST: `/elasticsearch_delete/invoke` 102 | 103 | ``` 104 | { 105 | "input":{ 106 | "elasticsearch_url":"", 107 | "elasticsearch_password":"", 108 | "index_name":"", 109 | "mode":"delete_index" 110 | "metadata_filter":{} 111 | } 112 | } 113 | ``` 114 | 115 | | param | desc | 116 | | ---------------------- | ------------------------------------------- | 117 | | elasticsearch_url | ElasticSearch URL | 118 | | elasticsearch_password | ElasticSearch password | 119 | | index_name | ElasticSearch index name | 120 | | mode | delete mode,`delete_index` or `delete_docs` | 121 | | metadata_filter | Filter document for metadata | 122 | 123 | ## Elasticsearch RAG 124 | 125 | this api is used to retrieve the knowledge from the Elastic Search 126 | 127 | ### LangServe API 128 | 129 | ```python 130 | remote_indexer = RemoteRunnable(RAG_SERVER_URL) 131 | 132 | result = remote_indexer.invoke({ 133 | "elasticsearch_url": ELASTICSEARCH_URL, 134 | "elasticsearch_password": ELASTICSEARCH_PASSWORD, 135 | "embed_model_address": embed_model_address, 136 | "index_name": "", 137 | "search_query": query, 138 | "metadata_filter": {}, 139 | "text_search_weight": 0.9, 140 | "rag_k": 10, 141 | "rag_num_candidates": 1000, 142 | "vector_search_weight": 0.1, 143 | "enable_rerank": false, 144 | "rerank_model_address": rerank_model_address, 145 | "rerank_top_k": 5, 146 | "enable_hyde_enhance":false, 147 | "hyde_enhance_base_url":"", 148 | "hyde_enhance_api_key":"", 149 | "hyde_enhance_temperature":0.7, 150 | "hyde_enhance_model":"", 151 | "hyde_prompt_key":"", 152 | }) 153 | 154 | ``` 155 | 156 | ### Rest API 157 | 158 | #### Request 159 | 160 | POST: `/elasticsearch_rag/invoke` 161 | 162 | ``` 163 | { 164 | "input":{ 165 | "elasticsearch_url":"", 166 | "elasticsearch_password":"", 167 | "embed_model_address":"", 168 | "enable_term_search": true, 169 | "enable_vector_search": true, 170 | "index_name":"", 171 | "search_query":"", 172 | "text_search_weight": 0.9, 173 | "rag_k": 5, 174 | "size": 5, 175 | "rag_num_candidates": 1000, 176 | "rag_num_passages": 5, 177 | "vector_search_weight": 0.1, 178 | "metadata_filter":{ 179 | 180 | }, 181 | "enable_rerank": false, 182 | "rerank_model_address":"", 183 | "rerank_top_k": 5, 184 | "enable_hyde_enhance":false, 185 | "hyde_enhance_base_url":"", 186 | "hyde_enhance_api_key":"", 187 | "hyde_enhance_temperature":0.7, 188 | "hyde_enhance_model":"", 189 | "hyde_prompt_key":"", 190 | 191 | } 192 | } 193 | ``` 194 | 195 | | param | desc | 196 | | ------------------------ | ------------------------------------------ | 197 | | elasticsearch_url | ElasticSearch URL | 198 | | elasticsearch_password | ElasticSearch password | 199 | | embed_model_address | Embedding model address ,for vector search | 200 | | enable_term_search | Enable ElasticSearch full text search | 201 | | enable_vector_search | Enable ElasticSearch vector search | 202 | | index_name | RAG ElasticSearch index name | 203 | | search_query | Search query | 204 | | text_search_weight | Weight for full text search | 205 | | rag_k | Number of top k documents to retrieve | 206 | | size | Number of documents to retrieve | 207 | | rag_num_candidates | Number of candidates for elasticsearch knn | 208 | | rag_num_passages | Number of passages for knn | 209 | | vector_search_weight | Weight for vector search | 210 | | metadata_filter | Filter document for metadata | 211 | | enable_rerank | Enable rerank | 212 | | rerank_model_address | Rerank model address | 213 | | rerank_top_k | Rerank top k | 214 | | enable_hyde_enhance | Enable hyde enhance | 215 | | hyde_enhance_base_url | Hyde enhance base url | 216 | | hyde_enhance_api_key | Hyde enhance api key | 217 | | hyde_enhance_temperature | Hyde enhance temperature | 218 | | hyde_enhance_model | Hyde enhance model | 219 | | hyde_prompt_key | Hyde prompt key | 220 | 221 | 222 | #### Response 223 | 224 | ``` 225 | { 226 | "output":[ 227 | { 228 | "id":"", 229 | "metadata":{ 230 | "_index":"", 231 | "_id":"", 232 | "_score":"", 233 | "_source":{ 234 | "metadata":{ 235 | "knowledge_type":"", 236 | "knowledge_id":1, 237 | "knowledge_title":"", 238 | "knowledge_folder_id":1, 239 | #custom metadata 240 | }, 241 | "vector":[] 242 | }, 243 | "relevance_score":0.0 # only rerank mode will have this field 244 | }, 245 | "page_content":"", 246 | "type":"Document" 247 | } 248 | ] 249 | } 250 | ``` 251 | 252 | ## Network Retrieval 253 | 254 | ### LangServe API 255 | 256 | ```python 257 | rag_server = RemoteRunnable(ONLINE_SEARCH_SERVER_URL) 258 | online_search_result: List[Document] = rag_server.invoke( 259 | { 260 | "query": user_message, 261 | } 262 | ) 263 | ``` 264 | 265 | ### Rest API 266 | #### Request 267 | 268 | POST: `/network_retrieval/invoke` 269 | 270 | ``` 271 | { 272 | "input":{ 273 | "query":"" 274 | } 275 | } 276 | ``` 277 | 278 | | param | desc | 279 | | ----- | --------------------------------------- | 280 | | query | Search statements for networked queries | 281 | 282 | #### Response 283 | 284 | ``` 285 | { 286 | "output":[ 287 | { 288 | "id":"", 289 | "metadata":{ 290 | 291 | }, 292 | "page_content":"", 293 | "type":"Document" 294 | } 295 | ] 296 | } 297 | ``` 298 | -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/KPCA.excalidraw: -------------------------------------------------------------------------------- 1 | { 2 | "type": "excalidraw", 3 | "version": 2, 4 | "source": "https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor", 5 | "elements": [ 6 | { 7 | "id": "bPnY7U2xo5MzQ2YQ35KQ2", 8 | "type": "rectangle", 9 | "x": 252.2595651970111, 10 | "y": 1802.0000305175781, 11 | "width": 133, 12 | "height": 45, 13 | "angle": 0, 14 | "strokeColor": "#1e1e1e", 15 | "backgroundColor": "transparent", 16 | "fillStyle": "hachure", 17 | "strokeWidth": 1, 18 | "strokeStyle": "solid", 19 | "roughness": 1, 20 | "opacity": 100, 21 | "groupIds": [], 22 | "frameId": null, 23 | "roundness": { 24 | "type": 3 25 | }, 26 | "seed": 587200559, 27 | "version": 104, 28 | "versionNonce": 1148462017, 29 | "isDeleted": false, 30 | "boundElements": [ 31 | { 32 | "type": "text", 33 | "id": "ftahCfPlQvBuL6ZmqlFtV" 34 | } 35 | ], 36 | "updated": 1698047444552, 37 | "link": null, 38 | "locked": false 39 | }, 40 | { 41 | "id": "ftahCfPlQvBuL6ZmqlFtV", 42 | "type": "text", 43 | "x": 279.53459724046814, 44 | "y": 1814.69086905022, 45 | "width": 78.44993591308594, 46 | "height": 19.618322934715955, 47 | "angle": 0, 48 | "strokeColor": "#1e1e1e", 49 | "backgroundColor": "transparent", 50 | "fillStyle": "hachure", 51 | "strokeWidth": 1, 52 | "strokeStyle": "solid", 53 | "roughness": 1, 54 | "opacity": 100, 55 | "groupIds": [], 56 | "frameId": null, 57 | "roundness": null, 58 | "seed": 40554113, 59 | "version": 189, 60 | "versionNonce": 1016857505, 61 | "isDeleted": false, 62 | "boundElements": null, 63 | "updated": 1698047444552, 64 | "link": null, 65 | "locked": false, 66 | "text": "数据预处理", 67 | "fontSize": 15.694658347772764, 68 | "fontFamily": 1, 69 | "textAlign": "center", 70 | "verticalAlign": "middle", 71 | "baseline": 13, 72 | "containerId": "bPnY7U2xo5MzQ2YQ35KQ2", 73 | "originalText": "数据预处理", 74 | "lineHeight": 1.25 75 | }, 76 | { 77 | "type": "rectangle", 78 | "version": 215, 79 | "versionNonce": 1034530369, 80 | "isDeleted": false, 81 | "id": "3cPOz3Y13SIelkZ-eEsez", 82 | "fillStyle": "hachure", 83 | "strokeWidth": 1, 84 | "strokeStyle": "solid", 85 | "roughness": 1, 86 | "opacity": 100, 87 | "angle": 0, 88 | "x": 443.2913714249871, 89 | "y": 1801.7557301958905, 90 | "strokeColor": "#1e1e1e", 91 | "backgroundColor": "transparent", 92 | "width": 132, 93 | "height": 45, 94 | "seed": 191755777, 95 | "groupIds": [], 96 | "frameId": null, 97 | "roundness": { 98 | "type": 3 99 | }, 100 | "boundElements": [ 101 | { 102 | "type": "text", 103 | "id": "kJTpSmKQh-B5qtCEDH0b0" 104 | } 105 | ], 106 | "updated": 1698047459254, 107 | "link": null, 108 | "locked": false 109 | }, 110 | { 111 | "type": "text", 112 | "version": 319, 113 | "versionNonce": 1002192417, 114 | "isDeleted": false, 115 | "id": "kJTpSmKQh-B5qtCEDH0b0", 116 | "fillStyle": "hachure", 117 | "strokeWidth": 1, 118 | "strokeStyle": "solid", 119 | "roughness": 1, 120 | "opacity": 100, 121 | "angle": 0, 122 | "x": 477.91139705975274, 123 | "y": 1814.4465687285324, 124 | "strokeColor": "#1e1e1e", 125 | "backgroundColor": "transparent", 126 | "width": 62.75994873046875, 127 | "height": 19.618322934715955, 128 | "seed": 555847137, 129 | "groupIds": [], 130 | "frameId": null, 131 | "roundness": null, 132 | "boundElements": [], 133 | "updated": 1698047459254, 134 | "link": null, 135 | "locked": false, 136 | "fontSize": 15.694658347772764, 137 | "fontFamily": 1, 138 | "text": "数据映射", 139 | "textAlign": "center", 140 | "verticalAlign": "middle", 141 | "containerId": "3cPOz3Y13SIelkZ-eEsez", 142 | "originalText": "数据映射", 143 | "lineHeight": 1.25, 144 | "baseline": 13 145 | }, 146 | { 147 | "type": "rectangle", 148 | "version": 306, 149 | "versionNonce": 136148769, 150 | "isDeleted": false, 151 | "id": "72Lc5UN8IyGqcxcqe8xaF", 152 | "fillStyle": "hachure", 153 | "strokeWidth": 1, 154 | "strokeStyle": "solid", 155 | "roughness": 1, 156 | "opacity": 100, 157 | "angle": 0, 158 | "x": 641.3333740234375, 159 | "y": 1800.641257375486, 160 | "strokeColor": "#1e1e1e", 161 | "backgroundColor": "transparent", 162 | "width": 131, 163 | "height": 45, 164 | "seed": 433230049, 165 | "groupIds": [], 166 | "frameId": null, 167 | "roundness": { 168 | "type": 3 169 | }, 170 | "boundElements": [ 171 | { 172 | "type": "text", 173 | "id": "reu00iOEoh46q0lkHQ_53" 174 | }, 175 | { 176 | "id": "MGh5R-g1SbmD8Akr9w1N6", 177 | "type": "arrow" 178 | }, 179 | { 180 | "id": "pwU8CYVu8wCoxNhYrVX7M", 181 | "type": "arrow" 182 | } 183 | ], 184 | "updated": 1698047493993, 185 | "link": null, 186 | "locked": false 187 | }, 188 | { 189 | "type": "text", 190 | "version": 421, 191 | "versionNonce": 592650337, 192 | "isDeleted": false, 193 | "id": "reu00iOEoh46q0lkHQ_53", 194 | "fillStyle": "hachure", 195 | "strokeWidth": 1, 196 | "strokeStyle": "solid", 197 | "roughness": 1, 198 | "opacity": 100, 199 | "angle": 0, 200 | "x": 675.4533996582031, 201 | "y": 1813.332095908128, 202 | "strokeColor": "#1e1e1e", 203 | "backgroundColor": "transparent", 204 | "width": 62.75994873046875, 205 | "height": 19.618322934715955, 206 | "seed": 1911540929, 207 | "groupIds": [], 208 | "frameId": null, 209 | "roundness": null, 210 | "boundElements": [], 211 | "updated": 1698047475714, 212 | "link": null, 213 | "locked": false, 214 | "fontSize": 15.694658347772764, 215 | "fontFamily": 1, 216 | "text": "特征提取", 217 | "textAlign": "center", 218 | "verticalAlign": "middle", 219 | "containerId": "72Lc5UN8IyGqcxcqe8xaF", 220 | "originalText": "特征提取", 221 | "lineHeight": 1.25, 222 | "baseline": 13 223 | }, 224 | { 225 | "type": "rectangle", 226 | "version": 264, 227 | "versionNonce": 736505039, 228 | "isDeleted": false, 229 | "id": "gQfAUF0XVduDwMu_JDNTN", 230 | "fillStyle": "hachure", 231 | "strokeWidth": 1, 232 | "strokeStyle": "solid", 233 | "roughness": 1, 234 | "opacity": 100, 235 | "angle": 0, 236 | "x": 835.3003193605402, 237 | "y": 1800.4771118087915, 238 | "strokeColor": "#1e1e1e", 239 | "backgroundColor": "transparent", 240 | "width": 130, 241 | "height": 45, 242 | "seed": 1939061089, 243 | "groupIds": [], 244 | "frameId": null, 245 | "roundness": { 246 | "type": 3 247 | }, 248 | "boundElements": [ 249 | { 250 | "type": "text", 251 | "id": "ru8f-BGVLmfvAFMf3QwE7" 252 | }, 253 | { 254 | "id": "X6zGh_lpCPWDwdWluSMb3", 255 | "type": "arrow" 256 | } 257 | ], 258 | "updated": 1698047497330, 259 | "link": null, 260 | "locked": false 261 | }, 262 | { 263 | "type": "text", 264 | "version": 389, 265 | "versionNonce": 897531375, 266 | "isDeleted": false, 267 | "id": "ru8f-BGVLmfvAFMf3QwE7", 268 | "fillStyle": "hachure", 269 | "strokeWidth": 1, 270 | "strokeStyle": "solid", 271 | "roughness": 1, 272 | "opacity": 100, 273 | "angle": 0, 274 | "x": 853.2303578126887, 275 | "y": 1813.1679503414334, 276 | "strokeColor": "#1e1e1e", 277 | "backgroundColor": "transparent", 278 | "width": 94.13992309570312, 279 | "height": 19.618322934715955, 280 | "seed": 980936001, 281 | "groupIds": [], 282 | "frameId": null, 283 | "roundness": null, 284 | "boundElements": [], 285 | "updated": 1698047470218, 286 | "link": null, 287 | "locked": false, 288 | "fontSize": 15.694658347772764, 289 | "fontFamily": 1, 290 | "text": "计算重构误差", 291 | "textAlign": "center", 292 | "verticalAlign": "middle", 293 | "containerId": "gQfAUF0XVduDwMu_JDNTN", 294 | "originalText": "计算重构误差", 295 | "lineHeight": 1.25, 296 | "baseline": 13 297 | }, 298 | { 299 | "type": "rectangle", 300 | "version": 277, 301 | "versionNonce": 1607369999, 302 | "isDeleted": false, 303 | "id": "7TKljqUrGMtp-KUFV35uc", 304 | "fillStyle": "hachure", 305 | "strokeWidth": 1, 306 | "strokeStyle": "solid", 307 | "roughness": 1, 308 | "opacity": 100, 309 | "angle": 0, 310 | "x": 1025.2532496404242, 311 | "y": 1799.5318676635275, 312 | "strokeColor": "#1e1e1e", 313 | "backgroundColor": "transparent", 314 | "width": 131, 315 | "height": 45, 316 | "seed": 772289231, 317 | "groupIds": [], 318 | "frameId": null, 319 | "roundness": { 320 | "type": 3 321 | }, 322 | "boundElements": [ 323 | { 324 | "type": "text", 325 | "id": "g1DQyzbaUHhXEIR9SYgUC" 326 | }, 327 | { 328 | "id": "X6zGh_lpCPWDwdWluSMb3", 329 | "type": "arrow" 330 | } 331 | ], 332 | "updated": 1698047497330, 333 | "link": null, 334 | "locked": false 335 | }, 336 | { 337 | "type": "text", 338 | "version": 394, 339 | "versionNonce": 1389016079, 340 | "isDeleted": false, 341 | "id": "g1DQyzbaUHhXEIR9SYgUC", 342 | "fillStyle": "hachure", 343 | "strokeWidth": 1, 344 | "strokeStyle": "solid", 345 | "roughness": 1, 346 | "opacity": 100, 347 | "angle": 0, 348 | "x": 1059.3732752751898, 349 | "y": 1812.2227061961694, 350 | "strokeColor": "#1e1e1e", 351 | "backgroundColor": "transparent", 352 | "width": 62.75994873046875, 353 | "height": 19.618322934715955, 354 | "seed": 792133871, 355 | "groupIds": [], 356 | "frameId": null, 357 | "roundness": null, 358 | "boundElements": [], 359 | "updated": 1698047480741, 360 | "link": null, 361 | "locked": false, 362 | "fontSize": 15.694658347772764, 363 | "fontFamily": 1, 364 | "text": "异常检测", 365 | "textAlign": "center", 366 | "verticalAlign": "middle", 367 | "containerId": "7TKljqUrGMtp-KUFV35uc", 368 | "originalText": "异常检测", 369 | "lineHeight": 1.25, 370 | "baseline": 13 371 | }, 372 | { 373 | "id": "PlkHWI-PSdONowv6MHysG", 374 | "type": "arrow", 375 | "x": 384, 376 | "y": 1824.6666717529297, 377 | "width": 59.333343505859375, 378 | "height": 0.6666717529296875, 379 | "angle": 0, 380 | "strokeColor": "#1e1e1e", 381 | "backgroundColor": "transparent", 382 | "fillStyle": "hachure", 383 | "strokeWidth": 1, 384 | "strokeStyle": "solid", 385 | "roughness": 1, 386 | "opacity": 100, 387 | "groupIds": [], 388 | "frameId": null, 389 | "roundness": { 390 | "type": 2 391 | }, 392 | "seed": 1512717391, 393 | "version": 35, 394 | "versionNonce": 1578845185, 395 | "isDeleted": false, 396 | "boundElements": null, 397 | "updated": 1698047485595, 398 | "link": null, 399 | "locked": false, 400 | "points": [ 401 | [ 402 | 0, 403 | 0 404 | ], 405 | [ 406 | 59.333343505859375, 407 | 0.6666717529296875 408 | ] 409 | ], 410 | "lastCommittedPoint": null, 411 | "startBinding": null, 412 | "endBinding": null, 413 | "startArrowhead": null, 414 | "endArrowhead": "arrow" 415 | }, 416 | { 417 | "id": "MGh5R-g1SbmD8Akr9w1N6", 418 | "type": "arrow", 419 | "x": 574.6666870117188, 420 | "y": 1824, 421 | "width": 65.33331298828125, 422 | "height": 0, 423 | "angle": 0, 424 | "strokeColor": "#1e1e1e", 425 | "backgroundColor": "transparent", 426 | "fillStyle": "hachure", 427 | "strokeWidth": 1, 428 | "strokeStyle": "solid", 429 | "roughness": 1, 430 | "opacity": 100, 431 | "groupIds": [], 432 | "frameId": null, 433 | "roundness": { 434 | "type": 2 435 | }, 436 | "seed": 217390049, 437 | "version": 38, 438 | "versionNonce": 1973420847, 439 | "isDeleted": false, 440 | "boundElements": null, 441 | "updated": 1698047490237, 442 | "link": null, 443 | "locked": false, 444 | "points": [ 445 | [ 446 | 0, 447 | 0 448 | ], 449 | [ 450 | 65.33331298828125, 451 | 0 452 | ] 453 | ], 454 | "lastCommittedPoint": null, 455 | "startBinding": null, 456 | "endBinding": { 457 | "elementId": "72Lc5UN8IyGqcxcqe8xaF", 458 | "focus": -0.038166338867287986, 459 | "gap": 1.3333740234375 460 | }, 461 | "startArrowhead": null, 462 | "endArrowhead": "arrow" 463 | }, 464 | { 465 | "id": "pwU8CYVu8wCoxNhYrVX7M", 466 | "type": "arrow", 467 | "x": 772.6666870117188, 468 | "y": 1824.6666717529297, 469 | "width": 63.33331298828125, 470 | "height": 0.6666717529296875, 471 | "angle": 0, 472 | "strokeColor": "#1e1e1e", 473 | "backgroundColor": "transparent", 474 | "fillStyle": "hachure", 475 | "strokeWidth": 1, 476 | "strokeStyle": "solid", 477 | "roughness": 1, 478 | "opacity": 100, 479 | "groupIds": [], 480 | "frameId": null, 481 | "roundness": { 482 | "type": 2 483 | }, 484 | "seed": 588137327, 485 | "version": 32, 486 | "versionNonce": 1140721473, 487 | "isDeleted": false, 488 | "boundElements": null, 489 | "updated": 1698047493993, 490 | "link": null, 491 | "locked": false, 492 | "points": [ 493 | [ 494 | 0, 495 | 0 496 | ], 497 | [ 498 | 63.33331298828125, 499 | 0.6666717529296875 500 | ] 501 | ], 502 | "lastCommittedPoint": null, 503 | "startBinding": { 504 | "elementId": "72Lc5UN8IyGqcxcqe8xaF", 505 | "focus": 0.035896736612991614, 506 | "gap": 1 507 | }, 508 | "endBinding": null, 509 | "startArrowhead": null, 510 | "endArrowhead": "arrow" 511 | }, 512 | { 513 | "id": "X6zGh_lpCPWDwdWluSMb3", 514 | "type": "arrow", 515 | "x": 966, 516 | "y": 1824, 517 | "width": 57.3333740234375, 518 | "height": 0.66668701171875, 519 | "angle": 0, 520 | "strokeColor": "#1e1e1e", 521 | "backgroundColor": "transparent", 522 | "fillStyle": "hachure", 523 | "strokeWidth": 1, 524 | "strokeStyle": "solid", 525 | "roughness": 1, 526 | "opacity": 100, 527 | "groupIds": [], 528 | "frameId": null, 529 | "roundness": { 530 | "type": 2 531 | }, 532 | "seed": 444852993, 533 | "version": 28, 534 | "versionNonce": 1933949679, 535 | "isDeleted": false, 536 | "boundElements": null, 537 | "updated": 1698047497330, 538 | "link": null, 539 | "locked": false, 540 | "points": [ 541 | [ 542 | 0, 543 | 0 544 | ], 545 | [ 546 | 57.3333740234375, 547 | 0.66668701171875 548 | ] 549 | ], 550 | "lastCommittedPoint": null, 551 | "startBinding": { 552 | "elementId": "gQfAUF0XVduDwMu_JDNTN", 553 | "focus": 0.01113336193375898, 554 | "gap": 1 555 | }, 556 | "endBinding": { 557 | "elementId": "7TKljqUrGMtp-KUFV35uc", 558 | "focus": -0.1469712883048789, 559 | "gap": 1.919875616986701 560 | }, 561 | "startArrowhead": null, 562 | "endArrowhead": "arrow" 563 | } 564 | ], 565 | "appState": { 566 | "gridSize": null, 567 | "viewBackgroundColor": "#ffffff" 568 | }, 569 | "files": {} 570 | } -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/OCSVM.excalidraw: -------------------------------------------------------------------------------- 1 | { 2 | "type": "excalidraw", 3 | "version": 2, 4 | "source": "https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor", 5 | "elements": [ 6 | { 7 | "id": "cnOuoXuwCKJAvgsO_I3_B", 8 | "type": "rectangle", 9 | "x": 544.666748046875, 10 | "y": 13.333328247070312, 11 | "width": 181, 12 | "height": 47, 13 | "angle": 0, 14 | "strokeColor": "#1e1e1e", 15 | "backgroundColor": "transparent", 16 | "fillStyle": "hachure", 17 | "strokeWidth": 1, 18 | "strokeStyle": "solid", 19 | "roughness": 1, 20 | "opacity": 100, 21 | "groupIds": [], 22 | "frameId": null, 23 | "roundness": { 24 | "type": 3 25 | }, 26 | "seed": 1637926806, 27 | "version": 216, 28 | "versionNonce": 1770240854, 29 | "isDeleted": false, 30 | "boundElements": [ 31 | { 32 | "type": "text", 33 | "id": "hohS3PRb8HjPbEyiSQOO5" 34 | }, 35 | { 36 | "id": "0x1HkdHQT6ungBfPZzNN1", 37 | "type": "arrow" 38 | } 39 | ], 40 | "updated": 1698053178019, 41 | "link": null, 42 | "locked": false 43 | }, 44 | { 45 | "id": "hohS3PRb8HjPbEyiSQOO5", 46 | "type": "text", 47 | "x": 561.819091796875, 48 | "y": 27.633328247070324, 49 | "width": 146.6953125, 50 | "height": 18.4, 51 | "angle": 0, 52 | "strokeColor": "#1e1e1e", 53 | "backgroundColor": "transparent", 54 | "fillStyle": "hachure", 55 | "strokeWidth": 1, 56 | "strokeStyle": "solid", 57 | "roughness": 1, 58 | "opacity": 100, 59 | "groupIds": [], 60 | "frameId": null, 61 | "roundness": null, 62 | "seed": 1282424406, 63 | "version": 252, 64 | "versionNonce": 1903148438, 65 | "isDeleted": false, 66 | "boundElements": null, 67 | "updated": 1698053174956, 68 | "link": null, 69 | "locked": false, 70 | "text": "X_train(均为正常)", 71 | "fontSize": 16, 72 | "fontFamily": 2, 73 | "textAlign": "center", 74 | "verticalAlign": "middle", 75 | "baseline": 15, 76 | "containerId": "cnOuoXuwCKJAvgsO_I3_B", 77 | "originalText": "X_train(均为正常)", 78 | "lineHeight": 1.15 79 | }, 80 | { 81 | "id": "vT_-80mx1iVG4OpK2CKyg", 82 | "type": "rectangle", 83 | "x": 545.3333435058594, 84 | "y": 119.33334350585938, 85 | "width": 182.66668701171875, 86 | "height": 42.66667175292969, 87 | "angle": 0, 88 | "strokeColor": "#1e1e1e", 89 | "backgroundColor": "transparent", 90 | "fillStyle": "hachure", 91 | "strokeWidth": 1, 92 | "strokeStyle": "solid", 93 | "roughness": 1, 94 | "opacity": 100, 95 | "groupIds": [], 96 | "frameId": null, 97 | "roundness": { 98 | "type": 3 99 | }, 100 | "seed": 1391190218, 101 | "version": 98, 102 | "versionNonce": 960585174, 103 | "isDeleted": false, 104 | "boundElements": [ 105 | { 106 | "type": "text", 107 | "id": "BvdOtp63671WM7Rf9kKdy" 108 | }, 109 | { 110 | "id": "0x1HkdHQT6ungBfPZzNN1", 111 | "type": "arrow" 112 | } 113 | ], 114 | "updated": 1698053178020, 115 | "link": null, 116 | "locked": false 117 | }, 118 | { 119 | "id": "BvdOtp63671WM7Rf9kKdy", 120 | "type": "text", 121 | "x": 604.6666870117188, 122 | "y": 131.46667938232423, 123 | "width": 64, 124 | "height": 18.4, 125 | "angle": 0, 126 | "strokeColor": "#1e1e1e", 127 | "backgroundColor": "transparent", 128 | "fillStyle": "hachure", 129 | "strokeWidth": 1, 130 | "strokeStyle": "solid", 131 | "roughness": 1, 132 | "opacity": 100, 133 | "groupIds": [], 134 | "frameId": null, 135 | "roundness": null, 136 | "seed": 779859210, 137 | "version": 79, 138 | "versionNonce": 1255067978, 139 | "isDeleted": false, 140 | "boundElements": null, 141 | "updated": 1698053139339, 142 | "link": null, 143 | "locked": false, 144 | "text": "特征转换", 145 | "fontSize": 16, 146 | "fontFamily": 2, 147 | "textAlign": "center", 148 | "verticalAlign": "middle", 149 | "baseline": 15, 150 | "containerId": "vT_-80mx1iVG4OpK2CKyg", 151 | "originalText": "特征转换", 152 | "lineHeight": 1.15 153 | }, 154 | { 155 | "type": "rectangle", 156 | "version": 168, 157 | "versionNonce": 1978322326, 158 | "isDeleted": false, 159 | "id": "-ty2Oolwmsn5t40Ke-5f3", 160 | "fillStyle": "hachure", 161 | "strokeWidth": 1, 162 | "strokeStyle": "solid", 163 | "roughness": 1, 164 | "opacity": 100, 165 | "angle": 0, 166 | "x": 791.0000305175781, 167 | "y": 115.99996185302734, 168 | "strokeColor": "#1e1e1e", 169 | "backgroundColor": "transparent", 170 | "width": 228, 171 | "height": 47, 172 | "seed": 126433494, 173 | "groupIds": [], 174 | "frameId": null, 175 | "roundness": { 176 | "type": 3 177 | }, 178 | "boundElements": [ 179 | { 180 | "type": "text", 181 | "id": "ghgfRDQz8iHTXRhJzso2T" 182 | }, 183 | { 184 | "id": "jlT45VAP4Yrb-RURH6Z9z", 185 | "type": "arrow" 186 | }, 187 | { 188 | "id": "1g-6XUg1vSG8211He2mn_", 189 | "type": "arrow" 190 | } 191 | ], 192 | "updated": 1698053161032, 193 | "link": null, 194 | "locked": false 195 | }, 196 | { 197 | "type": "text", 198 | "version": 185, 199 | "versionNonce": 1785577610, 200 | "isDeleted": false, 201 | "id": "ghgfRDQz8iHTXRhJzso2T", 202 | "fillStyle": "hachure", 203 | "strokeWidth": 1, 204 | "strokeStyle": "solid", 205 | "roughness": 1, 206 | "opacity": 100, 207 | "angle": 0, 208 | "x": 815.6523742675781, 209 | "y": 130.29996185302736, 210 | "strokeColor": "#1e1e1e", 211 | "backgroundColor": "transparent", 212 | "width": 178.6953125, 213 | "height": 18.4, 214 | "seed": 1255648790, 215 | "groupIds": [], 216 | "frameId": null, 217 | "roundness": null, 218 | "boundElements": [], 219 | "updated": 1698053141255, 220 | "link": null, 221 | "locked": false, 222 | "fontSize": 16, 223 | "fontFamily": 2, 224 | "text": "One-Class SVM模型训练", 225 | "textAlign": "center", 226 | "verticalAlign": "middle", 227 | "containerId": "-ty2Oolwmsn5t40Ke-5f3", 228 | "originalText": "One-Class SVM模型训练", 229 | "lineHeight": 1.15, 230 | "baseline": 15 231 | }, 232 | { 233 | "id": "BZDcYoLAEaFTsbJQTwI-h", 234 | "type": "rectangle", 235 | "x": 841.3333129882812, 236 | "y": 214.0000457763672, 237 | "width": 145, 238 | "height": 45, 239 | "angle": 0, 240 | "strokeColor": "#1e1e1e", 241 | "backgroundColor": "#ced4da", 242 | "fillStyle": "hachure", 243 | "strokeWidth": 1, 244 | "strokeStyle": "solid", 245 | "roughness": 1, 246 | "opacity": 100, 247 | "groupIds": [], 248 | "frameId": null, 249 | "roundness": { 250 | "type": 3 251 | }, 252 | "seed": 766026698, 253 | "version": 158, 254 | "versionNonce": 1412419786, 255 | "isDeleted": false, 256 | "boundElements": [ 257 | { 258 | "type": "text", 259 | "id": "KH3vbsFyIL03tGNOq5td8" 260 | }, 261 | { 262 | "id": "1g-6XUg1vSG8211He2mn_", 263 | "type": "arrow" 264 | } 265 | ], 266 | "updated": 1698053250309, 267 | "link": null, 268 | "locked": false 269 | }, 270 | { 271 | "id": "KH3vbsFyIL03tGNOq5td8", 272 | "type": "text", 273 | "x": 892.0442504882812, 274 | "y": 227.3000457763672, 275 | "width": 43.578125, 276 | "height": 18.4, 277 | "angle": 0, 278 | "strokeColor": "#1e1e1e", 279 | "backgroundColor": "transparent", 280 | "fillStyle": "hachure", 281 | "strokeWidth": 1, 282 | "strokeStyle": "solid", 283 | "roughness": 1, 284 | "opacity": 100, 285 | "groupIds": [], 286 | "frameId": null, 287 | "roundness": null, 288 | "seed": 1849602954, 289 | "version": 114, 290 | "versionNonce": 304675862, 291 | "isDeleted": false, 292 | "boundElements": null, 293 | "updated": 1698053200160, 294 | "link": null, 295 | "locked": false, 296 | "text": "model", 297 | "fontSize": 16, 298 | "fontFamily": 2, 299 | "textAlign": "center", 300 | "verticalAlign": "middle", 301 | "baseline": 15, 302 | "containerId": "BZDcYoLAEaFTsbJQTwI-h", 303 | "originalText": "model", 304 | "lineHeight": 1.15 305 | }, 306 | { 307 | "id": "jlT45VAP4Yrb-RURH6Z9z", 308 | "type": "arrow", 309 | "x": 727.3333740234375, 310 | "y": 142, 311 | "width": 62, 312 | "height": 0.666656494140625, 313 | "angle": 0, 314 | "strokeColor": "#1e1e1e", 315 | "backgroundColor": "#e9ecef", 316 | "fillStyle": "hachure", 317 | "strokeWidth": 1, 318 | "strokeStyle": "solid", 319 | "roughness": 1, 320 | "opacity": 100, 321 | "groupIds": [], 322 | "frameId": null, 323 | "roundness": { 324 | "type": 2 325 | }, 326 | "seed": 399056010, 327 | "version": 17, 328 | "versionNonce": 543672278, 329 | "isDeleted": false, 330 | "boundElements": null, 331 | "updated": 1698053152445, 332 | "link": null, 333 | "locked": false, 334 | "points": [ 335 | [ 336 | 0, 337 | 0 338 | ], 339 | [ 340 | 62, 341 | -0.666656494140625 342 | ] 343 | ], 344 | "lastCommittedPoint": null, 345 | "startBinding": null, 346 | "endBinding": { 347 | "elementId": "-ty2Oolwmsn5t40Ke-5f3", 348 | "focus": -0.023848507778594104, 349 | "gap": 1.666656494140625 350 | }, 351 | "startArrowhead": null, 352 | "endArrowhead": "arrow" 353 | }, 354 | { 355 | "id": "1g-6XUg1vSG8211He2mn_", 356 | "type": "arrow", 357 | "x": 906.6419109808214, 358 | "y": 166, 359 | "width": 2.059434575190835, 360 | "height": 46.66668701171875, 361 | "angle": 0, 362 | "strokeColor": "#1e1e1e", 363 | "backgroundColor": "#e9ecef", 364 | "fillStyle": "hachure", 365 | "strokeWidth": 1, 366 | "strokeStyle": "solid", 367 | "roughness": 1, 368 | "opacity": 100, 369 | "groupIds": [], 370 | "frameId": null, 371 | "roundness": { 372 | "type": 2 373 | }, 374 | "seed": 83614666, 375 | "version": 47, 376 | "versionNonce": 1114392278, 377 | "isDeleted": false, 378 | "boundElements": null, 379 | "updated": 1698053200160, 380 | "link": null, 381 | "locked": false, 382 | "points": [ 383 | [ 384 | 0, 385 | 0 386 | ], 387 | [ 388 | -2.059434575190835, 389 | 46.66668701171875 390 | ] 391 | ], 392 | "lastCommittedPoint": null, 393 | "startBinding": { 394 | "elementId": "-ty2Oolwmsn5t40Ke-5f3", 395 | "gap": 3.0000381469726562, 396 | "focus": -0.02436693809333689 397 | }, 398 | "endBinding": { 399 | "elementId": "BZDcYoLAEaFTsbJQTwI-h", 400 | "gap": 1.3333587646484375, 401 | "focus": -0.1401851624252063 402 | }, 403 | "startArrowhead": null, 404 | "endArrowhead": "arrow" 405 | }, 406 | { 407 | "id": "0x1HkdHQT6ungBfPZzNN1", 408 | "type": "arrow", 409 | "x": 634.6666870117188, 410 | "y": 60.66667175292969, 411 | "width": 0.66668701171875, 412 | "height": 56.00001525878906, 413 | "angle": 0, 414 | "strokeColor": "#1e1e1e", 415 | "backgroundColor": "#e9ecef", 416 | "fillStyle": "hachure", 417 | "strokeWidth": 1, 418 | "strokeStyle": "solid", 419 | "roughness": 1, 420 | "opacity": 100, 421 | "groupIds": [], 422 | "frameId": null, 423 | "roundness": { 424 | "type": 2 425 | }, 426 | "seed": 124560778, 427 | "version": 27, 428 | "versionNonce": 1063116950, 429 | "isDeleted": false, 430 | "boundElements": null, 431 | "updated": 1698053178020, 432 | "link": null, 433 | "locked": false, 434 | "points": [ 435 | [ 436 | 0, 437 | 0 438 | ], 439 | [ 440 | -0.66668701171875, 441 | 56.00001525878906 442 | ] 443 | ], 444 | "lastCommittedPoint": null, 445 | "startBinding": { 446 | "elementId": "cnOuoXuwCKJAvgsO_I3_B", 447 | "focus": 0.002382933697713885, 448 | "gap": 1 449 | }, 450 | "endBinding": { 451 | "elementId": "vT_-80mx1iVG4OpK2CKyg", 452 | "focus": -0.03223601111047831, 453 | "gap": 2.666656494140625 454 | }, 455 | "startArrowhead": null, 456 | "endArrowhead": "arrow" 457 | }, 458 | { 459 | "type": "rectangle", 460 | "version": 146, 461 | "versionNonce": 1651747606, 462 | "isDeleted": false, 463 | "id": "XRE9PYL_7kZ3QGIissy1y", 464 | "fillStyle": "hachure", 465 | "strokeWidth": 1, 466 | "strokeStyle": "solid", 467 | "roughness": 1, 468 | "opacity": 100, 469 | "angle": 0, 470 | "x": 550.6666564941406, 471 | "y": 214.66666412353516, 472 | "strokeColor": "#1e1e1e", 473 | "backgroundColor": "transparent", 474 | "width": 182.66668701171875, 475 | "height": 42.66667175292969, 476 | "seed": 819324310, 477 | "groupIds": [], 478 | "frameId": null, 479 | "roundness": { 480 | "type": 3 481 | }, 482 | "boundElements": [ 483 | { 484 | "type": "text", 485 | "id": "I0Ztl6UNs2n2inqe0OFQu" 486 | } 487 | ], 488 | "updated": 1698053183106, 489 | "link": null, 490 | "locked": false 491 | }, 492 | { 493 | "type": "text", 494 | "version": 136, 495 | "versionNonce": 1012685386, 496 | "isDeleted": false, 497 | "id": "I0Ztl6UNs2n2inqe0OFQu", 498 | "fillStyle": "hachure", 499 | "strokeWidth": 1, 500 | "strokeStyle": "solid", 501 | "roughness": 1, 502 | "opacity": 100, 503 | "angle": 0, 504 | "x": 619.3203125, 505 | "y": 226.8, 506 | "strokeColor": "#1e1e1e", 507 | "backgroundColor": "transparent", 508 | "width": 45.359375, 509 | "height": 18.4, 510 | "seed": 661701334, 511 | "groupIds": [], 512 | "frameId": null, 513 | "roundness": null, 514 | "boundElements": [], 515 | "updated": 1698053187900, 516 | "link": null, 517 | "locked": false, 518 | "fontSize": 16, 519 | "fontFamily": 2, 520 | "text": "X_test", 521 | "textAlign": "center", 522 | "verticalAlign": "middle", 523 | "containerId": "XRE9PYL_7kZ3QGIissy1y", 524 | "originalText": "X_test", 525 | "lineHeight": 1.15, 526 | "baseline": 15 527 | }, 528 | { 529 | "type": "arrow", 530 | "version": 96, 531 | "versionNonce": 766028746, 532 | "isDeleted": false, 533 | "id": "oASYExEpfcRLf3Ww9lJ5C", 534 | "fillStyle": "hachure", 535 | "strokeWidth": 1, 536 | "strokeStyle": "solid", 537 | "roughness": 1, 538 | "opacity": 100, 539 | "angle": 0, 540 | "x": 731.5297676457326, 541 | "y": 234.0307356677344, 542 | "strokeColor": "#1e1e1e", 543 | "backgroundColor": "#e9ecef", 544 | "width": 109.80360637770491, 545 | "height": 0, 546 | "seed": 1888831114, 547 | "groupIds": [], 548 | "frameId": null, 549 | "roundness": { 550 | "type": 2 551 | }, 552 | "boundElements": [], 553 | "updated": 1698053195716, 554 | "link": null, 555 | "locked": false, 556 | "startBinding": null, 557 | "endBinding": null, 558 | "lastCommittedPoint": null, 559 | "startArrowhead": null, 560 | "endArrowhead": "arrow", 561 | "points": [ 562 | [ 563 | 0, 564 | 0 565 | ], 566 | [ 567 | 109.80360637770491, 568 | 0 569 | ] 570 | ] 571 | }, 572 | { 573 | "id": "jh-vJK3Jfyl7VFR9jZXIY", 574 | "type": "arrow", 575 | "x": 986, 576 | "y": 236.66668701171875, 577 | "width": 72.66668701171875, 578 | "height": 0.0822008916746313, 579 | "angle": 0, 580 | "strokeColor": "#1e1e1e", 581 | "backgroundColor": "#e9ecef", 582 | "fillStyle": "hachure", 583 | "strokeWidth": 1, 584 | "strokeStyle": "solid", 585 | "roughness": 1, 586 | "opacity": 100, 587 | "groupIds": [], 588 | "frameId": null, 589 | "roundness": { 590 | "type": 2 591 | }, 592 | "seed": 2090692246, 593 | "version": 41, 594 | "versionNonce": 1822790614, 595 | "isDeleted": false, 596 | "boundElements": null, 597 | "updated": 1698053247426, 598 | "link": null, 599 | "locked": false, 600 | "points": [ 601 | [ 602 | 0, 603 | 0 604 | ], 605 | [ 606 | 72.66668701171875, 607 | 0.0822008916746313 608 | ] 609 | ], 610 | "lastCommittedPoint": null, 611 | "startBinding": null, 612 | "endBinding": { 613 | "elementId": "YFVyvO-EhDYb_yxOJBmxn", 614 | "gap": 6.6666259765625, 615 | "focus": 0 616 | }, 617 | "startArrowhead": null, 618 | "endArrowhead": "arrow" 619 | }, 620 | { 621 | "type": "rectangle", 622 | "version": 232, 623 | "versionNonce": 1754322582, 624 | "isDeleted": false, 625 | "id": "YFVyvO-EhDYb_yxOJBmxn", 626 | "fillStyle": "hachure", 627 | "strokeWidth": 1, 628 | "strokeStyle": "solid", 629 | "roughness": 1, 630 | "opacity": 100, 631 | "angle": 0, 632 | "x": 1065.3333129882812, 633 | "y": 215.3333511352539, 634 | "strokeColor": "#1e1e1e", 635 | "backgroundColor": "transparent", 636 | "width": 136, 637 | "height": 43, 638 | "seed": 1585019862, 639 | "groupIds": [], 640 | "frameId": null, 641 | "roundness": { 642 | "type": 3 643 | }, 644 | "boundElements": [ 645 | { 646 | "type": "text", 647 | "id": "iifp8HTKmhoizyuPxKLtE" 648 | }, 649 | { 650 | "id": "jh-vJK3Jfyl7VFR9jZXIY", 651 | "type": "arrow" 652 | } 653 | ], 654 | "updated": 1698053247426, 655 | "link": null, 656 | "locked": false 657 | }, 658 | { 659 | "type": "text", 660 | "version": 244, 661 | "versionNonce": 565225750, 662 | "isDeleted": false, 663 | "id": "iifp8HTKmhoizyuPxKLtE", 664 | "fillStyle": "hachure", 665 | "strokeWidth": 1, 666 | "strokeStyle": "solid", 667 | "roughness": 1, 668 | "opacity": 100, 669 | "angle": 0, 670 | "x": 1075.1106567382812, 671 | "y": 227.63335113525392, 672 | "strokeColor": "#1e1e1e", 673 | "backgroundColor": "transparent", 674 | "width": 116.4453125, 675 | "height": 18.4, 676 | "seed": 13078806, 677 | "groupIds": [], 678 | "frameId": null, 679 | "roundness": null, 680 | "boundElements": [], 681 | "updated": 1698053247426, 682 | "link": null, 683 | "locked": false, 684 | "fontSize": 16, 685 | "fontFamily": 2, 686 | "text": "距离/决策函数值", 687 | "textAlign": "center", 688 | "verticalAlign": "middle", 689 | "containerId": "YFVyvO-EhDYb_yxOJBmxn", 690 | "originalText": "距离/决策函数值", 691 | "lineHeight": 1.15, 692 | "baseline": 15 693 | } 694 | ], 695 | "appState": { 696 | "gridSize": null, 697 | "viewBackgroundColor": "#ffffff" 698 | }, 699 | "files": {} 700 | } -------------------------------------------------------------------------------- /site/api/aiops/anomaly/img/MAD.excalidraw: -------------------------------------------------------------------------------- 1 | { 2 | "type": "excalidraw", 3 | "version": 2, 4 | "source": "https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor", 5 | "elements": [ 6 | { 7 | "type": "rectangle", 8 | "version": 181, 9 | "versionNonce": 1057436186, 10 | "isDeleted": false, 11 | "id": "pANSFdcjECclFZ5fb1h33", 12 | "fillStyle": "hachure", 13 | "strokeWidth": 1, 14 | "strokeStyle": "solid", 15 | "roughness": 1, 16 | "opacity": 100, 17 | "angle": 0, 18 | "x": 204.2858450753348, 19 | "y": 145.71428353445873, 20 | "strokeColor": "#1e1e1e", 21 | "backgroundColor": "transparent", 22 | "width": 172, 23 | "height": 54, 24 | "seed": 1108649579, 25 | "groupIds": [], 26 | "frameId": null, 27 | "roundness": { 28 | "type": 3 29 | }, 30 | "boundElements": [ 31 | { 32 | "type": "text", 33 | "id": "2DYYY9qNVUoDSkOkHOwZe" 34 | }, 35 | { 36 | "id": "OJvL2BYSnkpa6wPFW9wNB", 37 | "type": "arrow" 38 | } 39 | ], 40 | "updated": 1697426916748, 41 | "link": null, 42 | "locked": false 43 | }, 44 | { 45 | "type": "text", 46 | "version": 247, 47 | "versionNonce": 1104046362, 48 | "isDeleted": false, 49 | "id": "2DYYY9qNVUoDSkOkHOwZe", 50 | "fillStyle": "hachure", 51 | "strokeWidth": 1, 52 | "strokeStyle": "solid", 53 | "roughness": 1, 54 | "opacity": 100, 55 | "angle": 0, 56 | "x": 216.9499075753348, 57 | "y": 163.51428353445874, 58 | "strokeColor": "#1e1e1e", 59 | "backgroundColor": "transparent", 60 | "width": 146.671875, 61 | "height": 18.4, 62 | "seed": 2048340997, 63 | "groupIds": [], 64 | "frameId": null, 65 | "roundness": null, 66 | "boundElements": [], 67 | "updated": 1697426902480, 68 | "link": null, 69 | "locked": false, 70 | "fontSize": 16, 71 | "fontFamily": 2, 72 | "text": "求指标A的中位数MA", 73 | "textAlign": "center", 74 | "verticalAlign": "middle", 75 | "containerId": "pANSFdcjECclFZ5fb1h33", 76 | "originalText": "求指标A的中位数MA", 77 | "lineHeight": 1.15, 78 | "baseline": 15 79 | }, 80 | { 81 | "type": "rectangle", 82 | "version": 331, 83 | "versionNonce": 854490246, 84 | "isDeleted": false, 85 | "id": "_c6KZoBDtHAwGZQ7xrqOj", 86 | "fillStyle": "hachure", 87 | "strokeWidth": 1, 88 | "strokeStyle": "solid", 89 | "roughness": 1, 90 | "opacity": 100, 91 | "angle": 0, 92 | "x": 470.23818097795754, 93 | "y": 148.76191602434432, 94 | "strokeColor": "#1e1e1e", 95 | "backgroundColor": "transparent", 96 | "width": 203, 97 | "height": 47, 98 | "seed": 873747290, 99 | "groupIds": [], 100 | "frameId": null, 101 | "roundness": { 102 | "type": 3 103 | }, 104 | "boundElements": [ 105 | { 106 | "type": "text", 107 | "id": "4GpUiFML1ugBqTt3N-NAs" 108 | }, 109 | { 110 | "id": "OJvL2BYSnkpa6wPFW9wNB", 111 | "type": "arrow" 112 | }, 113 | { 114 | "id": "J-y1q12Hg5wavVVXMxTyf", 115 | "type": "arrow" 116 | } 117 | ], 118 | "updated": 1697426921746, 119 | "link": null, 120 | "locked": false 121 | }, 122 | { 123 | "id": "4GpUiFML1ugBqTt3N-NAs", 124 | "type": "text", 125 | "x": 487.06630597795754, 126 | "y": 163.06191602434433, 127 | "width": 169.34375, 128 | "height": 18.4, 129 | "angle": 0, 130 | "strokeColor": "#1e1e1e", 131 | "backgroundColor": "transparent", 132 | "fillStyle": "hachure", 133 | "strokeWidth": 1, 134 | "strokeStyle": "solid", 135 | "roughness": 1, 136 | "opacity": 100, 137 | "groupIds": [], 138 | "frameId": null, 139 | "roundness": null, 140 | "seed": 739759750, 141 | "version": 198, 142 | "versionNonce": 1226192346, 143 | "isDeleted": false, 144 | "boundElements": null, 145 | "updated": 1697426902480, 146 | "link": null, 147 | "locked": false, 148 | "text": "B=A-MA(指标A减去MA)", 149 | "fontSize": 16, 150 | "fontFamily": 2, 151 | "textAlign": "center", 152 | "verticalAlign": "middle", 153 | "baseline": 15, 154 | "containerId": "_c6KZoBDtHAwGZQ7xrqOj", 155 | "originalText": "B=A-MA(指标A减去MA)", 156 | "lineHeight": 1.15 157 | }, 158 | { 159 | "type": "rectangle", 160 | "version": 323, 161 | "versionNonce": 1464232602, 162 | "isDeleted": false, 163 | "id": "31ogr8FtKgF_5PvbXz1ae", 164 | "fillStyle": "hachure", 165 | "strokeWidth": 1, 166 | "strokeStyle": "solid", 167 | "roughness": 1, 168 | "opacity": 100, 169 | "angle": 0, 170 | "x": 764.3572518484935, 171 | "y": 145.50005340576178, 172 | "strokeColor": "#1e1e1e", 173 | "backgroundColor": "transparent", 174 | "width": 203, 175 | "height": 47, 176 | "seed": 1397010458, 177 | "groupIds": [], 178 | "frameId": null, 179 | "roundness": { 180 | "type": 3 181 | }, 182 | "boundElements": [ 183 | { 184 | "type": "text", 185 | "id": "xiLSETYnEWhxtaxso5z50" 186 | } 187 | ], 188 | "updated": 1697426902480, 189 | "link": null, 190 | "locked": false 191 | }, 192 | { 193 | "type": "text", 194 | "version": 243, 195 | "versionNonce": 1990108166, 196 | "isDeleted": false, 197 | "id": "xiLSETYnEWhxtaxso5z50", 198 | "fillStyle": "hachure", 199 | "strokeWidth": 1, 200 | "strokeStyle": "solid", 201 | "roughness": 1, 202 | "opacity": 100, 203 | "angle": 0, 204 | "x": 770.5095955984935, 205 | "y": 159.8000534057618, 206 | "strokeColor": "#1e1e1e", 207 | "backgroundColor": "transparent", 208 | "width": 190.6953125, 209 | "height": 18.4, 210 | "seed": 36412634, 211 | "groupIds": [], 212 | "frameId": null, 213 | "roundness": null, 214 | "boundElements": [], 215 | "updated": 1697426902480, 216 | "link": null, 217 | "locked": false, 218 | "fontSize": 16, 219 | "fontFamily": 2, 220 | "text": "C=abs(B)(对B取绝对值)", 221 | "textAlign": "center", 222 | "verticalAlign": "middle", 223 | "containerId": "31ogr8FtKgF_5PvbXz1ae", 224 | "originalText": "C=abs(B)(对B取绝对值)", 225 | "lineHeight": 1.15, 226 | "baseline": 15 227 | }, 228 | { 229 | "type": "rectangle", 230 | "version": 353, 231 | "versionNonce": 1125255002, 232 | "isDeleted": false, 233 | "id": "vWUqp0F-2J9B5ayq0HnGE", 234 | "fillStyle": "hachure", 235 | "strokeWidth": 1, 236 | "strokeStyle": "solid", 237 | "roughness": 1, 238 | "opacity": 100, 239 | "angle": 0, 240 | "x": 796.8333740234374, 241 | "y": 274.30953652518133, 242 | "strokeColor": "#1e1e1e", 243 | "backgroundColor": "transparent", 244 | "width": 164, 245 | "height": 47, 246 | "seed": 1899767514, 247 | "groupIds": [], 248 | "frameId": null, 249 | "roundness": { 250 | "type": 3 251 | }, 252 | "boundElements": [ 253 | { 254 | "type": "text", 255 | "id": "VHMW90yQuts6zgh5vQjYo" 256 | } 257 | ], 258 | "updated": 1697426902480, 259 | "link": null, 260 | "locked": false 261 | }, 262 | { 263 | "type": "text", 264 | "version": 295, 265 | "versionNonce": 880292678, 266 | "isDeleted": false, 267 | "id": "VHMW90yQuts6zgh5vQjYo", 268 | "fillStyle": "hachure", 269 | "strokeWidth": 1, 270 | "strokeStyle": "solid", 271 | "roughness": 1, 272 | "opacity": 100, 273 | "angle": 0, 274 | "x": 820.6146240234374, 275 | "y": 288.60953652518134, 276 | "strokeColor": "#1e1e1e", 277 | "backgroundColor": "transparent", 278 | "width": 116.4375, 279 | "height": 18.4, 280 | "seed": 1199979418, 281 | "groupIds": [], 282 | "frameId": null, 283 | "roundness": null, 284 | "boundElements": [], 285 | "updated": 1697426902480, 286 | "link": null, 287 | "locked": false, 288 | "fontSize": 16, 289 | "fontFamily": 2, 290 | "text": "求C的中位数MC", 291 | "textAlign": "center", 292 | "verticalAlign": "middle", 293 | "containerId": "vWUqp0F-2J9B5ayq0HnGE", 294 | "originalText": "求C的中位数MC", 295 | "lineHeight": 1.15, 296 | "baseline": 15 297 | }, 298 | { 299 | "type": "rectangle", 300 | "version": 420, 301 | "versionNonce": 1426900058, 302 | "isDeleted": false, 303 | "id": "S1h0v7h8rYDwJH3Pet66q", 304 | "fillStyle": "hachure", 305 | "strokeWidth": 1, 306 | "strokeStyle": "solid", 307 | "roughness": 1, 308 | "opacity": 100, 309 | "angle": 0, 310 | "x": 477.92848423549106, 311 | "y": 275.6429410661969, 312 | "strokeColor": "#1e1e1e", 313 | "backgroundColor": "transparent", 314 | "width": 250, 315 | "height": 47, 316 | "seed": 796715014, 317 | "groupIds": [], 318 | "frameId": null, 319 | "roundness": { 320 | "type": 3 321 | }, 322 | "boundElements": [ 323 | { 324 | "type": "text", 325 | "id": "bgTmE_lVcIseV5stgNk-v" 326 | }, 327 | { 328 | "id": "AEYOl0X1-IZPPMYk7m6AB", 329 | "type": "arrow" 330 | } 331 | ], 332 | "updated": 1697426936399, 333 | "link": null, 334 | "locked": false 335 | }, 336 | { 337 | "type": "text", 338 | "version": 447, 339 | "versionNonce": 1994250886, 340 | "isDeleted": false, 341 | "id": "bgTmE_lVcIseV5stgNk-v", 342 | "fillStyle": "hachure", 343 | "strokeWidth": 1, 344 | "strokeStyle": "solid", 345 | "roughness": 1, 346 | "opacity": 100, 347 | "angle": 0, 348 | "x": 505.12770298549106, 349 | "y": 289.94294106619685, 350 | "strokeColor": "#1e1e1e", 351 | "backgroundColor": "transparent", 352 | "width": 195.6015625, 353 | "height": 18.4, 354 | "seed": 1089337158, 355 | "groupIds": [], 356 | "frameId": null, 357 | "roundness": null, 358 | "boundElements": [], 359 | "updated": 1697426902480, 360 | "link": null, 361 | "locked": false, 362 | "fontSize": 16, 363 | "fontFamily": 2, 364 | "text": "MAC=MC×1.4826(校正MC)", 365 | "textAlign": "center", 366 | "verticalAlign": "middle", 367 | "containerId": "S1h0v7h8rYDwJH3Pet66q", 368 | "originalText": "MAC=MC×1.4826(校正MC)", 369 | "lineHeight": 1.15, 370 | "baseline": 15 371 | }, 372 | { 373 | "type": "rectangle", 374 | "version": 392, 375 | "versionNonce": 2029817946, 376 | "isDeleted": false, 377 | "id": "t4FMkKJBB3bwSS8uU4dO2", 378 | "fillStyle": "hachure", 379 | "strokeWidth": 1, 380 | "strokeStyle": "solid", 381 | "roughness": 1, 382 | "opacity": 100, 383 | "angle": 0, 384 | "x": 163.47627476283492, 385 | "y": 277.3571308680943, 386 | "strokeColor": "#1e1e1e", 387 | "backgroundColor": "#a5d8ff", 388 | "width": 250, 389 | "height": 47, 390 | "seed": 204549850, 391 | "groupIds": [], 392 | "frameId": null, 393 | "roundness": { 394 | "type": 3 395 | }, 396 | "boundElements": [ 397 | { 398 | "type": "text", 399 | "id": "9vOxaspguN97wlkRD43oC" 400 | } 401 | ], 402 | "updated": 1697426985691, 403 | "link": null, 404 | "locked": false 405 | }, 406 | { 407 | "type": "text", 408 | "version": 497, 409 | "versionNonce": 76323270, 410 | "isDeleted": false, 411 | "id": "9vOxaspguN97wlkRD43oC", 412 | "fillStyle": "hachure", 413 | "strokeWidth": 1, 414 | "strokeStyle": "solid", 415 | "roughness": 1, 416 | "opacity": 100, 417 | "angle": 0, 418 | "x": 193.63643101283492, 419 | "y": 291.65713086809427, 420 | "strokeColor": "#1e1e1e", 421 | "backgroundColor": "transparent", 422 | "width": 189.6796875, 423 | "height": 18.4, 424 | "seed": 1318732698, 425 | "groupIds": [], 426 | "frameId": null, 427 | "roundness": null, 428 | "boundElements": [], 429 | "updated": 1697426902480, 430 | "link": null, 431 | "locked": false, 432 | "fontSize": 16, 433 | "fontFamily": 2, 434 | "text": "正常范围:MA±倍数×MAD", 435 | "textAlign": "center", 436 | "verticalAlign": "middle", 437 | "containerId": "t4FMkKJBB3bwSS8uU4dO2", 438 | "originalText": "正常范围:MA±倍数×MAD", 439 | "lineHeight": 1.15, 440 | "baseline": 15 441 | }, 442 | { 443 | "id": "bWWRaACzv4VPwl72uwFcm", 444 | "type": "diamond", 445 | "x": 191.30954415457597, 446 | "y": 364.97623225620816, 447 | "width": 185, 448 | "height": 80, 449 | "angle": 0, 450 | "strokeColor": "#1e1e1e", 451 | "backgroundColor": "transparent", 452 | "fillStyle": "hachure", 453 | "strokeWidth": 1, 454 | "strokeStyle": "solid", 455 | "roughness": 1, 456 | "opacity": 100, 457 | "groupIds": [], 458 | "frameId": null, 459 | "roundness": { 460 | "type": 2 461 | }, 462 | "seed": 1815406042, 463 | "version": 179, 464 | "versionNonce": 1783332378, 465 | "isDeleted": false, 466 | "boundElements": [ 467 | { 468 | "type": "text", 469 | "id": "vacaa1XOR7wEEFbcVvT_A" 470 | } 471 | ], 472 | "updated": 1697426945615, 473 | "link": null, 474 | "locked": false 475 | }, 476 | { 477 | "id": "vacaa1XOR7wEEFbcVvT_A", 478 | "type": "text", 479 | "x": 244.05954415457597, 480 | "y": 395.7762322562082, 481 | "width": 80, 482 | "height": 18.4, 483 | "angle": 0, 484 | "strokeColor": "#1e1e1e", 485 | "backgroundColor": "transparent", 486 | "fillStyle": "hachure", 487 | "strokeWidth": 1, 488 | "strokeStyle": "solid", 489 | "roughness": 1, 490 | "opacity": 100, 491 | "groupIds": [], 492 | "frameId": null, 493 | "roundness": null, 494 | "seed": 1469394394, 495 | "version": 117, 496 | "versionNonce": 1797827290, 497 | "isDeleted": false, 498 | "boundElements": null, 499 | "updated": 1697426945615, 500 | "link": null, 501 | "locked": false, 502 | "text": "超出范围?", 503 | "fontSize": 16, 504 | "fontFamily": 2, 505 | "textAlign": "center", 506 | "verticalAlign": "middle", 507 | "baseline": 15, 508 | "containerId": "bWWRaACzv4VPwl72uwFcm", 509 | "originalText": "超出范围?", 510 | "lineHeight": 1.15 511 | }, 512 | { 513 | "id": "xM2ZT5LgpkAYCalgK80Si", 514 | "type": "rectangle", 515 | "x": 438.92856270926336, 516 | "y": 379.26192474365234, 517 | "width": 105.71428571428578, 518 | "height": 50.47618321010043, 519 | "angle": 0, 520 | "strokeColor": "#1e1e1e", 521 | "backgroundColor": "#ffc9c9", 522 | "fillStyle": "hachure", 523 | "strokeWidth": 1, 524 | "strokeStyle": "solid", 525 | "roughness": 1, 526 | "opacity": 100, 527 | "groupIds": [], 528 | "frameId": null, 529 | "roundness": { 530 | "type": 3 531 | }, 532 | "seed": 373132378, 533 | "version": 96, 534 | "versionNonce": 1767704262, 535 | "isDeleted": false, 536 | "boundElements": [ 537 | { 538 | "type": "text", 539 | "id": "bwfEufG-s-CM9Fzlk5vzb" 540 | }, 541 | { 542 | "id": "_isvgepn_MPPuM8BPrz0l", 543 | "type": "arrow" 544 | } 545 | ], 546 | "updated": 1697426977636, 547 | "link": null, 548 | "locked": false 549 | }, 550 | { 551 | "id": "bwfEufG-s-CM9Fzlk5vzb", 552 | "type": "text", 553 | "x": 475.78570556640625, 554 | "y": 395.30001634870257, 555 | "width": 32, 556 | "height": 18.4, 557 | "angle": 0, 558 | "strokeColor": "#1e1e1e", 559 | "backgroundColor": "transparent", 560 | "fillStyle": "hachure", 561 | "strokeWidth": 1, 562 | "strokeStyle": "solid", 563 | "roughness": 1, 564 | "opacity": 100, 565 | "groupIds": [], 566 | "frameId": null, 567 | "roundness": null, 568 | "seed": 562258310, 569 | "version": 54, 570 | "versionNonce": 550190170, 571 | "isDeleted": false, 572 | "boundElements": null, 573 | "updated": 1697426945615, 574 | "link": null, 575 | "locked": false, 576 | "text": "异常", 577 | "fontSize": 16, 578 | "fontFamily": 2, 579 | "textAlign": "center", 580 | "verticalAlign": "middle", 581 | "baseline": 15, 582 | "containerId": "xM2ZT5LgpkAYCalgK80Si", 583 | "originalText": "异常", 584 | "lineHeight": 1.15 585 | }, 586 | { 587 | "type": "rectangle", 588 | "version": 154, 589 | "versionNonce": 714280282, 590 | "isDeleted": false, 591 | "id": "C7mn7PXdimC8auHMScxZt", 592 | "fillStyle": "hachure", 593 | "strokeWidth": 1, 594 | "strokeStyle": "solid", 595 | "roughness": 1, 596 | "opacity": 100, 597 | "angle": 0, 598 | "x": 232.7381155831473, 599 | "y": 490.2143020629883, 600 | "strokeColor": "#1e1e1e", 601 | "backgroundColor": "#b2f2bb", 602 | "width": 105.71428571428578, 603 | "height": 50.47618321010043, 604 | "seed": 650252762, 605 | "groupIds": [], 606 | "frameId": null, 607 | "roundness": { 608 | "type": 3 609 | }, 610 | "boundElements": [ 611 | { 612 | "type": "text", 613 | "id": "W2NH_9sHYFFRhddDpmFeF" 614 | }, 615 | { 616 | "id": "dCbpSba_K3vO-gsX6LsLc", 617 | "type": "arrow" 618 | } 619 | ], 620 | "updated": 1697426979837, 621 | "link": null, 622 | "locked": false 623 | }, 624 | { 625 | "type": "text", 626 | "version": 124, 627 | "versionNonce": 1092054490, 628 | "isDeleted": false, 629 | "id": "W2NH_9sHYFFRhddDpmFeF", 630 | "fillStyle": "hachure", 631 | "strokeWidth": 1, 632 | "strokeStyle": "solid", 633 | "roughness": 1, 634 | "opacity": 100, 635 | "angle": 0, 636 | "x": 269.5952584402902, 637 | "y": 506.2523936680385, 638 | "strokeColor": "#1e1e1e", 639 | "backgroundColor": "transparent", 640 | "width": 32, 641 | "height": 18.4, 642 | "seed": 1259783834, 643 | "groupIds": [], 644 | "frameId": null, 645 | "roundness": null, 646 | "boundElements": [], 647 | "updated": 1697426945615, 648 | "link": null, 649 | "locked": false, 650 | "fontSize": 16, 651 | "fontFamily": 2, 652 | "text": "正常", 653 | "textAlign": "center", 654 | "verticalAlign": "middle", 655 | "containerId": "C7mn7PXdimC8auHMScxZt", 656 | "originalText": "正常", 657 | "lineHeight": 1.15, 658 | "baseline": 15 659 | }, 660 | { 661 | "id": "OJvL2BYSnkpa6wPFW9wNB", 662 | "type": "arrow", 663 | "x": 378.92860630580356, 664 | "y": 174.4523936680385, 665 | "width": 90.47620500837058, 666 | "height": 0, 667 | "angle": 0, 668 | "strokeColor": "#1e1e1e", 669 | "backgroundColor": "transparent", 670 | "fillStyle": "hachure", 671 | "strokeWidth": 1, 672 | "strokeStyle": "solid", 673 | "roughness": 1, 674 | "opacity": 100, 675 | "groupIds": [], 676 | "frameId": null, 677 | "roundness": { 678 | "type": 2 679 | }, 680 | "seed": 2097843974, 681 | "version": 47, 682 | "versionNonce": 374202074, 683 | "isDeleted": false, 684 | "boundElements": null, 685 | "updated": 1697426916748, 686 | "link": null, 687 | "locked": false, 688 | "points": [ 689 | [ 690 | 0, 691 | 0 692 | ], 693 | [ 694 | 90.47620500837058, 695 | 0 696 | ] 697 | ], 698 | "lastCommittedPoint": null, 699 | "startBinding": { 700 | "elementId": "pANSFdcjECclFZ5fb1h33", 701 | "focus": 0.06437444939184321, 702 | "gap": 2.64276123046875 703 | }, 704 | "endBinding": { 705 | "elementId": "_c6KZoBDtHAwGZQ7xrqOj", 706 | "focus": -0.09321181462528426, 707 | "gap": 1 708 | }, 709 | "startArrowhead": null, 710 | "endArrowhead": "arrow" 711 | }, 712 | { 713 | "id": "J-y1q12Hg5wavVVXMxTyf", 714 | "type": "arrow", 715 | "x": 675.1190970284598, 716 | "y": 172.54763902936662, 717 | "width": 89.52383858816972, 718 | "height": 4.761897495814708, 719 | "angle": 0, 720 | "strokeColor": "#1e1e1e", 721 | "backgroundColor": "transparent", 722 | "fillStyle": "hachure", 723 | "strokeWidth": 1, 724 | "strokeStyle": "solid", 725 | "roughness": 1, 726 | "opacity": 100, 727 | "groupIds": [], 728 | "frameId": null, 729 | "roundness": { 730 | "type": 2 731 | }, 732 | "seed": 53702746, 733 | "version": 30, 734 | "versionNonce": 1047860550, 735 | "isDeleted": false, 736 | "boundElements": null, 737 | "updated": 1697426921746, 738 | "link": null, 739 | "locked": false, 740 | "points": [ 741 | [ 742 | 0, 743 | 0 744 | ], 745 | [ 746 | 89.52383858816972, 747 | -4.761897495814708 748 | ] 749 | ], 750 | "lastCommittedPoint": null, 751 | "startBinding": { 752 | "elementId": "_c6KZoBDtHAwGZQ7xrqOj", 753 | "focus": 0.20016998864870336, 754 | "gap": 1.8809160505022646 755 | }, 756 | "endBinding": null, 757 | "startArrowhead": null, 758 | "endArrowhead": "arrow" 759 | }, 760 | { 761 | "id": "pPyFc-S1XmczICx_cuZiU", 762 | "type": "arrow", 763 | "x": 868.452401297433, 764 | "y": 191.59525081089566, 765 | "width": 2.8571428571428896, 766 | "height": 83.80955287388389, 767 | "angle": 0, 768 | "strokeColor": "#1e1e1e", 769 | "backgroundColor": "transparent", 770 | "fillStyle": "hachure", 771 | "strokeWidth": 1, 772 | "strokeStyle": "solid", 773 | "roughness": 1, 774 | "opacity": 100, 775 | "groupIds": [], 776 | "frameId": null, 777 | "roundness": { 778 | "type": 2 779 | }, 780 | "seed": 2050554822, 781 | "version": 40, 782 | "versionNonce": 401483802, 783 | "isDeleted": false, 784 | "boundElements": null, 785 | "updated": 1697426926529, 786 | "link": null, 787 | "locked": false, 788 | "points": [ 789 | [ 790 | 0, 791 | 0 792 | ], 793 | [ 794 | 2.8571428571428896, 795 | 83.80955287388389 796 | ] 797 | ], 798 | "lastCommittedPoint": null, 799 | "startBinding": null, 800 | "endBinding": null, 801 | "startArrowhead": null, 802 | "endArrowhead": "arrow" 803 | }, 804 | { 805 | "id": "L9Ds36P6MXd0jvek-ob3X", 806 | "type": "arrow", 807 | "x": 797.0238298688616, 808 | "y": 297.3095365251814, 809 | "width": 69.52375139508933, 810 | "height": 0.9524100167410552, 811 | "angle": 0, 812 | "strokeColor": "#1e1e1e", 813 | "backgroundColor": "transparent", 814 | "fillStyle": "hachure", 815 | "strokeWidth": 1, 816 | "strokeStyle": "solid", 817 | "roughness": 1, 818 | "opacity": 100, 819 | "groupIds": [], 820 | "frameId": null, 821 | "roundness": { 822 | "type": 2 823 | }, 824 | "seed": 1659245786, 825 | "version": 21, 826 | "versionNonce": 179453830, 827 | "isDeleted": false, 828 | "boundElements": null, 829 | "updated": 1697426931448, 830 | "link": null, 831 | "locked": false, 832 | "points": [ 833 | [ 834 | 0, 835 | 0 836 | ], 837 | [ 838 | -69.52375139508933, 839 | 0.9524100167410552 840 | ] 841 | ], 842 | "lastCommittedPoint": null, 843 | "startBinding": null, 844 | "endBinding": null, 845 | "startArrowhead": null, 846 | "endArrowhead": "arrow" 847 | }, 848 | { 849 | "id": "AEYOl0X1-IZPPMYk7m6AB", 850 | "type": "arrow", 851 | "x": 477.02382986886164, 852 | "y": 299.2143129621233, 853 | "width": 63.80950927734375, 854 | "height": 2.8571428571428896, 855 | "angle": 0, 856 | "strokeColor": "#1e1e1e", 857 | "backgroundColor": "transparent", 858 | "fillStyle": "hachure", 859 | "strokeWidth": 1, 860 | "strokeStyle": "solid", 861 | "roughness": 1, 862 | "opacity": 100, 863 | "groupIds": [], 864 | "frameId": null, 865 | "roundness": { 866 | "type": 2 867 | }, 868 | "seed": 1250713286, 869 | "version": 22, 870 | "versionNonce": 420792218, 871 | "isDeleted": false, 872 | "boundElements": null, 873 | "updated": 1697426936399, 874 | "link": null, 875 | "locked": false, 876 | "points": [ 877 | [ 878 | 0, 879 | 0 880 | ], 881 | [ 882 | -63.80950927734375, 883 | 2.8571428571428896 884 | ] 885 | ], 886 | "lastCommittedPoint": null, 887 | "startBinding": { 888 | "elementId": "S1h0v7h8rYDwJH3Pet66q", 889 | "focus": 0.19129628918040004, 890 | "gap": 1 891 | }, 892 | "endBinding": null, 893 | "startArrowhead": null, 894 | "endArrowhead": "arrow" 895 | }, 896 | { 897 | "id": "hVkTbwgAkddZb-CGEd-x1", 898 | "type": "arrow", 899 | "x": 281.78574916294644, 900 | "y": 323.02382223946705, 901 | "width": 1.9047764369420292, 902 | "height": 42.85720825195318, 903 | "angle": 0, 904 | "strokeColor": "#1e1e1e", 905 | "backgroundColor": "transparent", 906 | "fillStyle": "hachure", 907 | "strokeWidth": 1, 908 | "strokeStyle": "solid", 909 | "roughness": 1, 910 | "opacity": 100, 911 | "groupIds": [], 912 | "frameId": null, 913 | "roundness": { 914 | "type": 2 915 | }, 916 | "seed": 1919363354, 917 | "version": 74, 918 | "versionNonce": 1929826010, 919 | "isDeleted": false, 920 | "boundElements": null, 921 | "updated": 1697426957808, 922 | "link": null, 923 | "locked": false, 924 | "points": [ 925 | [ 926 | 0, 927 | 0 928 | ], 929 | [ 930 | 1.9047764369420292, 931 | 42.85720825195318 932 | ] 933 | ], 934 | "lastCommittedPoint": null, 935 | "startBinding": null, 936 | "endBinding": null, 937 | "startArrowhead": null, 938 | "endArrowhead": "arrow" 939 | }, 940 | { 941 | "id": "_isvgepn_MPPuM8BPrz0l", 942 | "type": "arrow", 943 | "x": 370.357177734375, 944 | "y": 404.928598676409, 945 | "width": 66.66665213448664, 946 | "height": 2.857142857142833, 947 | "angle": 0, 948 | "strokeColor": "#1e1e1e", 949 | "backgroundColor": "transparent", 950 | "fillStyle": "hachure", 951 | "strokeWidth": 1, 952 | "strokeStyle": "solid", 953 | "roughness": 1, 954 | "opacity": 100, 955 | "groupIds": [], 956 | "frameId": null, 957 | "roundness": { 958 | "type": 2 959 | }, 960 | "seed": 1796815622, 961 | "version": 33, 962 | "versionNonce": 2132081562, 963 | "isDeleted": false, 964 | "boundElements": null, 965 | "updated": 1697426968530, 966 | "link": null, 967 | "locked": false, 968 | "points": [ 969 | [ 970 | 0, 971 | 0 972 | ], 973 | [ 974 | 66.66665213448664, 975 | -2.857142857142833 976 | ] 977 | ], 978 | "lastCommittedPoint": null, 979 | "startBinding": null, 980 | "endBinding": { 981 | "elementId": "xM2ZT5LgpkAYCalgK80Si", 982 | "focus": 0.1736330373613678, 983 | "gap": 1.9047328404017208 984 | }, 985 | "startArrowhead": null, 986 | "endArrowhead": "arrow" 987 | }, 988 | { 989 | "id": "dCbpSba_K3vO-gsX6LsLc", 990 | "type": "arrow", 991 | "x": 283.6905255998885, 992 | "y": 441.1190893990653, 993 | "width": 0.9524100167410552, 994 | "height": 48.571428571428555, 995 | "angle": 0, 996 | "strokeColor": "#1e1e1e", 997 | "backgroundColor": "transparent", 998 | "fillStyle": "hachure", 999 | "strokeWidth": 1, 1000 | "strokeStyle": "solid", 1001 | "roughness": 1, 1002 | "opacity": 100, 1003 | "groupIds": [], 1004 | "frameId": null, 1005 | "roundness": { 1006 | "type": 2 1007 | }, 1008 | "seed": 1424645402, 1009 | "version": 24, 1010 | "versionNonce": 1919414534, 1011 | "isDeleted": false, 1012 | "boundElements": null, 1013 | "updated": 1697426973594, 1014 | "link": null, 1015 | "locked": false, 1016 | "points": [ 1017 | [ 1018 | 0, 1019 | 0 1020 | ], 1021 | [ 1022 | 0.9524100167410552, 1023 | 48.571428571428555 1024 | ] 1025 | ], 1026 | "lastCommittedPoint": null, 1027 | "startBinding": null, 1028 | "endBinding": { 1029 | "elementId": "C7mn7PXdimC8auHMScxZt", 1030 | "focus": -0.008381548995006318, 1031 | "gap": 1 1032 | }, 1033 | "startArrowhead": null, 1034 | "endArrowhead": "arrow" 1035 | } 1036 | ], 1037 | "appState": { 1038 | "gridSize": null, 1039 | "viewBackgroundColor": "#ffffff" 1040 | }, 1041 | "files": {} 1042 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published 637 | by the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . --------------------------------------------------------------------------------