├── .env ├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── README-CN.md ├── README.md ├── agent.py ├── bootstrap ├── rss.bs ├── summarize.bs └── t.bs ├── command.py ├── doc ├── chat-gpt-simple.gif ├── chat-gpt1.png ├── chat-gpt2.png ├── demo.gif ├── gpt-online-demo.gif ├── screen.png └── screen_cn.png ├── env.py ├── httpstream3.py ├── interpreter3.py ├── main.py ├── old ├── amazon.json ├── friend.json ├── hot.json ├── httpserver.py ├── httpstream.py ├── interpreter.py ├── music.json ├── rss.json ├── spider.json ├── summarize.json ├── v2-hot.json ├── while.json └── writecode.json ├── support └── fun │ └── function.py └── utils ├── file.py ├── json.py ├── parse.py └── templateEngine.py /.env: -------------------------------------------------------------------------------- 1 | api_key=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 2 | api_base=https://chatgpt-api.shn.hk/v1/ 3 | server_port=9981 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .* -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.linting.flake8Enabled": true, 3 | "python.linting.enabled": true, 4 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 weekend-project-space 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README-CN.md: -------------------------------------------------------------------------------- 1 | # bootstrap-gpt 2 | 3 | > 引导 gpt 帮你高效完成各种事情,可以联网,支持 prompts 编排,没有完全 auto 更多自定义空间,自己编排任务流 4 | 5 | ![bootstrap-gpt](./doc/gpt-online-demo.gif) 6 | ![bootstrap-gpt](./doc/screen_cn.png) 7 | 8 | ## 下载 9 | 10 | ## 设置 api key 11 | 12 | .env 13 | 14 | ``` 15 | api_key=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 16 | ``` 17 | 18 | ## 运行 19 | 20 | ``` 21 | cd bootstrap-gpt 22 | 23 | pip install openai && pip install beautifulsoup4 && pip install jsonpath && pip install jinja2 24 | 25 | python3 ./main.py 26 | ``` 27 | 28 | ## http server 29 | 30 | ``` 31 | > python3 main.py serve 32 | 33 | Bootstrap-GPT server v1.0.0 34 | 35 | ➜ Api: http://localhost:9981/v1/chat/completions 36 | ➜ Web: https://weekendproject.space/chat-gpt-online 37 | ``` 38 | 39 | **api** 40 | 41 | ``` 42 | post /v1/chat/completions 43 | {"messages":[{"role":"user","content":"v2-hot"}],"model":"gpt-3.5-turbo"} 44 | ``` 45 | 46 | res 47 | 48 | ``` 49 | {"choices": [{"message": {"role": "assistant", "content": "hello"}]} 50 | ``` 51 | 52 | 配合 [chat-gpt-online](https://weekendproject.space/chat-gpt-online.html) 食用效果更佳 53 | 54 | > 注意需要设置一个 api-key(xxx 即可) 55 | 56 | ## 引导示例 57 | 58 | - summarize.json 59 | 60 | ``` 61 | { 62 | "author": "ruidong", 63 | "date": "2023-04-19", 64 | "version": "0.1", 65 | "description": "总结网页", 66 | "boot": [{ 67 | "w": "请输入网址", 68 | "r": "r0", 69 | "p": "spider:{{r0}}:select=article" 70 | }, { 71 | "p": "chat:总结一下这个页面介绍了什么{{m0}}" 72 | }, { 73 | "w": "总结: {{m1}} \n还要总结其他网页吗? y/n", 74 | "r": "r2", 75 | "b": { 76 | "y": 0, 77 | "n": -1 78 | } 79 | }] 80 | } 81 | ``` 82 | 83 | - w: write 支持模板变量 84 | - r: read 读取输入 85 | - b: branch 分支 支持 Object 字段 eq 跳转 和 Array 循序执行 或 无继续往下执行 86 | - p: prompt 支持模板变量 微指令 用于引导 chatgpt[chat:] 给其文案 或 爬虫[sprider:]搜索 纯文本[text:]输出, 可以扩展更多微指令提示引导 87 | 88 | r2 r1 为变量名称 为类型+index 索引 有 r:reader w:writer p:prompts m:msg 之分 89 | 90 | 生成规则参考[interpreter.py](./interpreter.py) 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bootstrap-gpt 2 | 3 | > 引导 GPT 帮助您高效地完成各种任务,gpt-plugin, 可联网,总结网页,突破字数限制,支持 prompt 编排,可自动化, 支持 web api 4 | 5 | ![bootstrap-gpt](./doc/chat-gpt-simple.gif) 6 | 7 | ## translate 8 | 9 | [中文](./README-CN.md) 10 | 11 | ## 下载 12 | 13 | ## 设置 api key 14 | 15 | .env 16 | 17 | ``` 18 | api_key=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 19 | api_base=https://chatgpt-api.shn.hk/v1/ 20 | server_port=9981 21 | ``` 22 | 23 | ## 运行 24 | 25 | ``` 26 | cd bootstrap-gpt 27 | 28 | pip install openai beautifulsoup4 jsonpath html2text flask flask-sse 29 | 30 | python3 ./main.py 31 | ``` 32 | 33 | ## http server 34 | 35 | ``` 36 | > python3 main.py serve 37 | 38 | 39 | Bootstrap-GPT server v1.0.0 40 | 41 | ➜ Api: http://localhost:9981/v1/chat/completions 42 | ➜ Web: https://weekendproject.space/chat-gpt-online 43 | 44 | ``` 45 | 46 | **api** 47 | 48 | ``` 49 | post /v1/chat/completions 50 | {"messages":[{"role":"user","content":"v2-hot"}],"model":"gpt-3.5-turbo"} 51 | ``` 52 | 53 | res 54 | 55 | ``` 56 | {"choices": [{"message": {"role": "assistant", "content": "hello"}]} 57 | ``` 58 | 59 | coordination [chat-gpt-online](https://weekendproject.space/chat-gpt-online.html) Better eating effect 60 | 61 | > Note that you need to set an api-key (xxx is enough) 62 | 63 | ## bootstrap 示例 64 | 65 | ``` 66 | 总结网页 67 | ------ 68 | : summarizelabel 69 | > 请输入网页 $ 70 | > $ url 71 | @ spider:{{url}}::select=body art 72 | @ chat:总结一下{{art}} summarize 73 | > 总结: {{summarize}} \n还要总结其他网页吗? y/n 74 | > $ yes 75 | ^ {{yes}} summarizelabel 76 | ``` 77 | 78 | - . : 标签 79 | 80 | - . > 移动/打印 81 | 82 | - . < 读取 83 | 84 | - . @ 调用自定义过程 spider,chat,len,-,text-len 85 | 86 | - . ^ 分支跳转 跳转标签或数字所在行 87 | 88 | 解释器[interpreter3.py](./interpreter3.py) 89 | -------------------------------------------------------------------------------- /agent.py: -------------------------------------------------------------------------------- 1 | import json 2 | import logging 3 | import re 4 | import openai 5 | import requests 6 | from bs4 import BeautifulSoup 7 | from utils.json import to_obj 8 | from jsonpath import jsonpath 9 | from env import env 10 | from utils.parse import parseone 11 | import html2text as ht 12 | 13 | reg = 'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F]'\ 14 | + '[0-9a-fA-F]))+' 15 | # print(env) 16 | # 设置 OpenAI API 密钥 17 | openai.api_key = env['api_key'] 18 | openai.api_base = env['api_base'] 19 | 20 | 21 | def spider(query): 22 | url = query 23 | params = {} 24 | headers = { 25 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 \ 26 | (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36", 27 | } 28 | 29 | if query.find('::') > 0: 30 | arr = query.split('::') 31 | url = arr[0] 32 | params = parseone(arr[1], '=') 33 | else: 34 | pass 35 | res = requests.get(url, headers=headers) 36 | res.encoding = res.apparent_encoding 37 | # print(query, params, res.text) 38 | if 'select' in params: 39 | soup = BeautifulSoup(res.text, "html.parser") 40 | t = soup.select(params['select']) 41 | str = '' 42 | for item in t: 43 | str += item.get_text() 44 | return str 45 | elif 'jsonpath' in params: 46 | return jsonpath(to_obj(res.text), params['jsonpath']) 47 | elif 'tojson' in params: 48 | return to_obj(res.text) 49 | else: 50 | return res.text 51 | 52 | 53 | def gpt_agent(content): 54 | # print(content) 55 | # 创建 OpenAI GPT 对象 56 | response = openai.ChatCompletion.create( 57 | model="gpt-3.5-turbo", 58 | messages=[ 59 | {"role": "user", "content": content}, 60 | ] 61 | ) 62 | 63 | result = '' 64 | for choice in response.choices: 65 | result += choice.message.content 66 | return result 67 | 68 | 69 | def gpt_agent_stream(content, messages): 70 | if len(messages) < 2: 71 | messages = [ 72 | {"role": "user", "content": content}, 73 | ] 74 | if len(messages) > 1: 75 | messages[len(messages)-1]['content'] = content 76 | # print(content) 77 | # 创建 OpenAI GPT 对象 78 | response = openai.ChatCompletion.create( 79 | model="gpt-3.5-turbo", 80 | messages=messages, 81 | stream=True 82 | ) 83 | return response 84 | 85 | 86 | def gpt_agent_http_stream(content, messages): 87 | str = _link2text(content) 88 | # print(str) 89 | # return str 90 | return gpt_agent_stream(str, messages) 91 | 92 | 93 | def _link2text(content): 94 | links = re.findall(reg, content) 95 | for link in links: 96 | text = spider('{}::select=body'.format(link)).strip() 97 | content = content.replace(link, '{}'.format(re.sub('\n+', ' ', text))) 98 | return content 99 | 100 | 101 | def decrease(env, key): 102 | v = int(env[key])-1 103 | env[key] = v 104 | return v 105 | 106 | 107 | def increase(env, key): 108 | v = int(env[key])+1 109 | env[key] = v 110 | return v 111 | 112 | 113 | def len0(env, key): 114 | return len(env[key]) 115 | 116 | 117 | def textlen0(data): 118 | if data == 'None': 119 | return 0 120 | else: 121 | return len(data) 122 | 123 | 124 | def set(env, exp): 125 | kv = exp.split('=') 126 | k = kv[0].trim() 127 | v = kv[1].trim() 128 | v = env[v] if v in env else v 129 | if k in env: 130 | env[k] = v 131 | return v 132 | else: 133 | return None 134 | 135 | 136 | def define(env, exp): 137 | kv = exp.split('=') 138 | k = kv[0].trim() 139 | v = kv[1].trim() 140 | v = env[v] if v in env else v 141 | if k in env: 142 | return None 143 | else: 144 | env[k] = v 145 | return v 146 | 147 | 148 | def html2md(data): 149 | text_maker = ht.HTML2Text() 150 | text_maker.bypass_tables = False 151 | md = text_maker.handle(data) 152 | return md 153 | 154 | 155 | def agent(content, env, prompt): 156 | index = content.find(':') 157 | agentName = content[:index] 158 | promp = content[index+1:].strip() 159 | # print(promp) 160 | # print(str(index)+agentName+'---' + promt) 161 | if agentName == 'chat': 162 | return gpt_agent(promp) 163 | elif agentName == 'spider': 164 | return spider(promp) 165 | elif agentName == 'html2md': 166 | return html2md(promp) 167 | elif agentName == '-': 168 | return decrease(env, promp) 169 | elif agentName == '+': 170 | return increase(env, promp) 171 | elif agentName == 'set!': 172 | return set(env, promp) 173 | elif agentName == 'define': 174 | return define(env, promp) 175 | elif agentName == 'len': 176 | return len0(env, promp) 177 | elif agentName == 'text-len': 178 | return textlen0(promp) 179 | else: 180 | return promp 181 | -------------------------------------------------------------------------------- /bootstrap/rss.bs: -------------------------------------------------------------------------------- 1 | 查看rss信息 2 | ------ 3 | > 查看什么主题 $ 4 | > $ query 5 | @ spider:https://api.webfollow.cc/api/channels/ids?search={{query}}::tojson m0 6 | @ spider:https://api.webfollow.cc/api/channels/articles?size=10&id={{m0[0]}}::jsonpath=$.content[*] m1 7 | @ len:m1 m2 8 | @ len:m1 m3 9 | : artslabel 10 | > {{m3 - m2 + 1}} [{{(m1[m3-m2])['channelName']}}] {{(m1[m3-m2])['title']}} $ 11 | @ -:m2 m2 12 | ^ {{m2}} artslabel 13 | : look 14 | > 请输入编号查看文章 $ 15 | > $ index 16 | @ spider:https://api.webfollow.cc/api/articles/{{m1[(index|int)-1].id}}::tojson m6 17 | @ text-len:{{m6['enclosure']}} enclosure 18 | ^ {{enclosure}} podcast 19 | : rss 20 | > ## {{m6['title']}} \n * {{m6['channelName']}} {{m6['pubDateTime']}} \n \n {{m6['description']}} \n 查看原文\n $ 21 | ^ 1 look 22 | : podcast 23 | > ## {{m6['title']}} \n * {{m6['channelName']}} {{m6['pubDateTime']}} \n \n {{m6['description']}} \n 查看原文\n $ 24 | ^ 1 look -------------------------------------------------------------------------------- /bootstrap/summarize.bs: -------------------------------------------------------------------------------- 1 | 总结网页 2 | ------ 3 | : summarizelabel 4 | > 请输入网页 $ 5 | > $ url 6 | @ spider:{{url}}::select=body art 7 | @ chat:总结一下{{art}} summarize 8 | > 总结: {{summarize}} \n还要总结其他网页吗? y/n 9 | > $ yes 10 | ^ {{yes}} summarizelabel -------------------------------------------------------------------------------- /bootstrap/t.bs: -------------------------------------------------------------------------------- 1 | demo 2 | ------ 3 | > 你好世界 $ 4 | > $ $ 5 | : label1 6 | > $ c 7 | > hello world-{{c}} d 8 | > {{d}} $ 9 | > 是否继续0/1 $ 10 | < y $ 11 | ^ {{y}} label1 12 | @ chat:今天星期几 out 13 | > {{out}} $ -------------------------------------------------------------------------------- /command.py: -------------------------------------------------------------------------------- 1 | import cmd 2 | from agent import gpt_agent 3 | from interpreter3 import Bootwarp, handler 4 | from httpstream3 import startserver 5 | from support.fun.function import loadFuncs 6 | 7 | 8 | class Command(cmd.Cmd): 9 | prompt = '\033[34m>\033[0m ' 10 | 11 | def __init__(self, config, severPort, completekey='tab', stdin=None, 12 | stdout=None): 13 | super().__init__(completekey=completekey, stdin=stdin, stdout=stdout) 14 | self.config = config 15 | self.severPort = severPort 16 | self.io = IOHolder(self.stdin, self.stdout, Command.prompt) 17 | 18 | def preloop(self): 19 | self.io.print('\n\033[34mBootstrap GPT\033[0m\ 20 | \n\033[35msample > use summarize\033[0m \n \n') 21 | 22 | def do_ls(self, arg): 23 | boots = self.config.keys() 24 | print(self.config) 25 | for b in boots: 26 | self.io.println('{} : {} ' 27 | .format(b, getBootDesc(self.config, b))) 28 | 29 | def do_use(self, arg): 30 | if arg in self.config: 31 | boot = getBoot(self.config, arg) 32 | env = loadFuncs() 33 | bootwarp = Bootwarp(boot, env=env, io=self.io) 34 | handler(bootwarp) 35 | self.io.println('bye '+arg+'!') 36 | else: 37 | self.io.println('\033[31mnot found bootstarap: '+arg+'!\033[0m ') 38 | 39 | def do_serve(self, arg): 40 | startserver(self.config, self.severPort) 41 | 42 | def do_chat(self, arg): 43 | self.io.println('chat: {}'.format(gpt_agent(arg))) 44 | 45 | def do_exit(self, arg): 46 | self.io.println('Exiting...') 47 | return True 48 | 49 | 50 | def getBoot(config, name): 51 | lines = config[name].split('\n') 52 | if len(lines) > 1 and lines[1] == '------': 53 | return lines[2:] 54 | else: 55 | return lines 56 | 57 | 58 | def getBootDesc(config, name): 59 | lines = config[name].split('\n') 60 | if len(lines) > 1 and lines[1] == '------': 61 | return lines[0] 62 | else: 63 | return name 64 | 65 | 66 | class IOHolder: 67 | 68 | def __init__(self, stdin=None, stdout=None, prompt='>'): 69 | self.stdin = stdin 70 | self.stdout = stdout 71 | self.prompt = prompt 72 | 73 | def println(self, o): 74 | if isinstance(o, list): 75 | for i in o: 76 | self.stdout.write(i) 77 | self.stdout.write('\n') 78 | else: 79 | self.stdout.write(o) 80 | self.stdout.write('\n') 81 | self.stdout.flush() 82 | 83 | def print(self, o): 84 | self.stdout.write(o) 85 | self.stdout.flush() 86 | 87 | def readline(self): 88 | line = self.stdin.readline() 89 | if not len(line): 90 | line = 'EOF' 91 | else: 92 | line = line.rstrip('\r\n') 93 | return line 94 | -------------------------------------------------------------------------------- /doc/chat-gpt-simple.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weekend-project-space/bootstrap-gpt/254067c898e98b298a6345475d744ec7aaae7342/doc/chat-gpt-simple.gif -------------------------------------------------------------------------------- /doc/chat-gpt1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weekend-project-space/bootstrap-gpt/254067c898e98b298a6345475d744ec7aaae7342/doc/chat-gpt1.png -------------------------------------------------------------------------------- /doc/chat-gpt2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weekend-project-space/bootstrap-gpt/254067c898e98b298a6345475d744ec7aaae7342/doc/chat-gpt2.png -------------------------------------------------------------------------------- /doc/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weekend-project-space/bootstrap-gpt/254067c898e98b298a6345475d744ec7aaae7342/doc/demo.gif -------------------------------------------------------------------------------- /doc/gpt-online-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weekend-project-space/bootstrap-gpt/254067c898e98b298a6345475d744ec7aaae7342/doc/gpt-online-demo.gif -------------------------------------------------------------------------------- /doc/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weekend-project-space/bootstrap-gpt/254067c898e98b298a6345475d744ec7aaae7342/doc/screen.png -------------------------------------------------------------------------------- /doc/screen_cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weekend-project-space/bootstrap-gpt/254067c898e98b298a6345475d744ec7aaae7342/doc/screen_cn.png -------------------------------------------------------------------------------- /env.py: -------------------------------------------------------------------------------- 1 | from utils.file import readfile 2 | from utils.parse import parse 3 | 4 | env = parse(readfile('.env')) 5 | -------------------------------------------------------------------------------- /httpstream3.py: -------------------------------------------------------------------------------- 1 | import json 2 | import time 3 | from flask import Flask, Response, request 4 | from agent import gpt_agent_http_stream 5 | from interpreter3 import Bootwarp, IOHolder, handler 6 | from support.fun.function import loadFuncs 7 | import logging 8 | 9 | 10 | class Env: 11 | def __init__(self, bootName, env, index) -> None: 12 | self.bootName = bootName 13 | self.env = env 14 | self.index = index 15 | 16 | 17 | env = Env('', {}, 0) 18 | app = Flask(__name__) 19 | 20 | 21 | @app.route("/") 22 | def index(): 23 | return "Hello World" 24 | 25 | 26 | @app.route("/v1/models") 27 | def models(): 28 | return { 29 | "object": "list", 30 | "data": [ 31 | { 32 | "id": "gpt-3.5-turbo", 33 | "object": "model", 34 | "created": 1677610602, 35 | "owned_by": "openai", 36 | "permission": [ 37 | { 38 | "id": "modelperm-lZPGJwrxyPjMHAm856z8yLf8", 39 | "object": "model_permission", 40 | "allow_create_engine": False, 41 | "allow_sampling": True, 42 | "allow_logprobs": True, 43 | "allow_search_indices": False, 44 | "allow_view": True, 45 | "allow_fine_tuning": False, 46 | "organization": "*", 47 | "group": None, 48 | "is_blocking": False 49 | } 50 | ], 51 | "root": "gpt-3.5-turbo", 52 | "parent": None 53 | }, 54 | ] 55 | } 56 | 57 | 58 | @app.route("/v1/chat/completions", methods=['GET', 'POST']) 59 | def stream(): 60 | msg = request.args.get('msg') 61 | messages = [] 62 | if not msg: 63 | req = request.get_json() 64 | messages = req['messages'] 65 | msg = messages[len(messages)-1]['content'] 66 | return Response(inter(msg, messages), mimetype="text/event-stream") 67 | 68 | 69 | def interpreter(msg, messages=[]): 70 | logging.debug(msg) 71 | bootwarp.io.clear() 72 | if msg == 'exit': 73 | restEnv() 74 | return 'bye!' 75 | elif msg == 'ls': 76 | boots = config.keys() 77 | res = [] 78 | for b in boots: 79 | res.append('{} : {} '.format(b, getBootDesc(b))) 80 | return res 81 | elif msg in config: 82 | restEnv() 83 | bootwarp.setBoot(getBoot(msg)) 84 | handler(bootwarp, input=msg, interruptRead=True, r=True) 85 | writer = bootwarp.io 86 | if not bootwarp.hasNext(): 87 | restEnv() 88 | writer.println('bye !') 89 | return writer.content 90 | else: 91 | return writer.content 92 | elif bootwarp.hasBoot(): 93 | handler(bootwarp, input=msg, interruptRead=True, r=True) 94 | writer = bootwarp.io 95 | if not bootwarp.hasNext(): 96 | restEnv() 97 | writer.println('bye !') 98 | return writer.content 99 | else: 100 | return writer.content 101 | else: 102 | return gpt_agent_http_stream(msg, messages) 103 | 104 | 105 | def restEnv(): 106 | env = loadFuncs(True) 107 | global bootwarp 108 | bootwarp = Bootwarp(None, env=env, io=Writer()) 109 | 110 | 111 | class Writer(IOHolder): 112 | 113 | def __init__(self) -> None: 114 | self.content = [] 115 | 116 | def println(self, o): 117 | if isinstance(o, list): 118 | for i in o: 119 | self.content.append(i) 120 | else: 121 | self.content.append(o) 122 | 123 | def print(self, o): 124 | if isinstance(o, list): 125 | for i in o: 126 | self.content.append(i) 127 | else: 128 | self.content.append(o) 129 | 130 | def clear(self): 131 | self.content = [] 132 | 133 | 134 | def inter(req, messages=[]): 135 | res = interpreter(req, messages) 136 | if res: 137 | if isinstance(res, list): 138 | if len(res) < 3: 139 | yield warp(" \n".join(res), True) 140 | else: 141 | for i in res: 142 | time.sleep(0.1) 143 | yield warp(' - {} \n'.format(i)) 144 | yield warp(None, True) 145 | elif isinstance(res, str): 146 | yield warp(res, True) 147 | elif isinstance(res, object): 148 | for event in res: 149 | yield json.dumps(event, ensure_ascii=False) 150 | else: 151 | yield warp(res, True) 152 | else: 153 | pass 154 | 155 | 156 | def getBoot(name): 157 | lines = config[name].split('\n') 158 | if len(lines) > 1 and lines[1] == '------': 159 | return lines[2:] 160 | else: 161 | return lines 162 | 163 | 164 | def getBootDesc(name): 165 | lines = config[name].split('\n') 166 | if len(lines) > 1 and lines[1] == '------': 167 | return lines[0] 168 | else: 169 | return name 170 | 171 | 172 | def warp(content, stop=False): 173 | return json.dumps( 174 | obj={"choices": [{"delta": {"content": content}, 175 | "finish_reason": "stop" if stop else None}]}, 176 | ensure_ascii=False 177 | ) 178 | 179 | 180 | def startserver(config0, port): 181 | global config 182 | config = config0 183 | env = loadFuncs(True) 184 | global bootwarp 185 | bootwarp = Bootwarp(None, env=env, io=Writer()) 186 | print('\n\033[34mBootstrap-GPT server\033[0m v1.0.0 \n') 187 | print('\033[34m➜\033[0m Api: \033[36m\ 188 | http://localhost:{}/v1/chat/completions\033[0m' 189 | .format(port)) 190 | print('\033[34m➜\033[0m Web: \033[36m\ 191 | http://localhost:3000\033[0m') 192 | print('\n') 193 | app.run(port=port) 194 | -------------------------------------------------------------------------------- /interpreter3.py: -------------------------------------------------------------------------------- 1 | import sys 2 | # import logging 3 | 4 | 5 | class Instr: 6 | 7 | def __init__(self, key, args, target) -> None: 8 | self.key = key 9 | self.args = args 10 | self.target = target 11 | 12 | def __str__(self) -> str: 13 | return (self.key, self.args, self.target).__str__() 14 | 15 | 16 | class Bootwarp: 17 | 18 | def __init__(self, boot, index=0, env={}, io=None) -> None: 19 | self.boot = boot 20 | self.index = 0 21 | self.env = env 22 | self.io = io 23 | self.initLable() 24 | self.index = index 25 | 26 | def initLable(self): 27 | if self.boot: 28 | for i in range(len(self.boot)): 29 | instr = Bootwarp.getInstr0(self.boot, i) 30 | if instr.key == ':': 31 | self.env[instr.args] = i 32 | 33 | def getInstr(self) -> Instr: 34 | return Bootwarp.getInstr0(self.boot, self.index) 35 | 36 | def getInstr0(boot, index) -> Instr: 37 | instr_str = boot[index].strip() 38 | left_index = instr_str.find(" ") 39 | right_index = instr_str.rfind(" ") 40 | key = instr_str[0:left_index] 41 | args = instr_str[left_index+1:] 42 | target = None 43 | if right_index != left_index: 44 | args = instr_str[left_index+1: right_index] 45 | target = instr_str[right_index+1:] 46 | return Instr(key, args, target) 47 | 48 | def setBoot(self, boot): 49 | self.boot = boot 50 | self.index = 0 51 | self.initLable() 52 | self.index = 0 53 | 54 | def setIndex(self, index=0): 55 | self.index = index 56 | 57 | def hasNext(self) -> bool: 58 | return self.boot and len(self.boot)-1 > self.index and self.index > -1 59 | 60 | def next(self): 61 | self.index += 1 62 | 63 | def isReadInstr(self): 64 | instr = self.getInstr() 65 | if instr.key == '<': 66 | return True 67 | elif instr.key == '>' and instr.args == '$': 68 | return True 69 | else: 70 | return False 71 | 72 | def hasBoot(self): 73 | return True if self.boot else False 74 | 75 | 76 | class IOHolder: 77 | 78 | def __init__(self, stdin=sys.stdin, stdout=sys.stdout, prompt='>'): 79 | self.stdin = stdin 80 | self.stdout = stdout 81 | self.prompt = prompt 82 | 83 | def println(self, o): 84 | if isinstance(o, list): 85 | for i in o: 86 | self.stdout.write(i) 87 | self.stdout.write('\n') 88 | else: 89 | self.stdout.write(o) 90 | self.stdout.write('\n') 91 | self.stdout.flush() 92 | 93 | def print(self, o): 94 | self.stdout.write(o) 95 | self.stdout.flush() 96 | 97 | def readline(self): 98 | if self.line: 99 | line = self.line 100 | self.line = None 101 | return line 102 | else: 103 | line = self.stdin.readline() 104 | if not len(line): 105 | line = 'EOF' 106 | else: 107 | line = line.rstrip('\r\n') 108 | return line 109 | 110 | def setLine(self, str): 111 | self.line = str 112 | 113 | 114 | def inter0(bootwarp, instr): 115 | func = bootwarp.env[instr.key] 116 | if func: 117 | func(bootwarp, instr) 118 | else: 119 | bootwarp.io.println('error: undefind '+instr.key) 120 | 121 | 122 | def handler(bootwarp, input=None, interruptRead=False, r=False): 123 | # logging.info(input, bootwarp.index) 124 | if interruptRead and bootwarp.isReadInstr() and not r: 125 | return True 126 | else: 127 | if bootwarp.isReadInstr() and input: 128 | bootwarp.io.setLine(input) 129 | else: 130 | pass 131 | instr = bootwarp.getInstr() 132 | inter0(bootwarp, instr) 133 | if bootwarp.hasNext(): 134 | bootwarp.next() 135 | handler(bootwarp, input, interruptRead) 136 | pass 137 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from command import Command 3 | from utils.file import listdir, readfile 4 | from httpstream3 import startserver 5 | from env import env 6 | 7 | 8 | def loadConfig(): 9 | path = "bootstrap" 10 | dir = listdir(path) 11 | config = {} 12 | for filename in dir: 13 | file = path+'/'+filename 14 | config[filename.replace('.bs', '')] = readfile(file) 15 | return config 16 | 17 | 18 | def main(args): 19 | severPort = int(env['server_port']) 20 | if len(args) > 1 and args[1] == 'serve': 21 | startserver(loadConfig(), severPort) 22 | else: 23 | Command(loadConfig(), severPort).cmdloop() 24 | 25 | 26 | if __name__ == '__main__': 27 | main(sys.argv) 28 | -------------------------------------------------------------------------------- /old/amazon.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ruidong", 3 | "date": "2023-04-17", 4 | "version": "0.1", 5 | "description": "amazon review 助手", 6 | "boot": [{ 7 | "w": "请输入商品评论链接", 8 | "r": "r0", 9 | "p": "spider:{{r0}}::select=[data-hook=review-body]" 10 | }, { 11 | "w": "{{m0}} 是否查看总结y/n", 12 | "r": "r1", 13 | "b": { 14 | "n": -1 15 | } 16 | }, { 17 | "p": "chat:用中文分析一下客户反馈最多的问题?并给出占比:{{m0}}" 18 | }, { 19 | "w": "总结:{{m2}}" 20 | }] 21 | } -------------------------------------------------------------------------------- /old/friend.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ruidong", 3 | "date": "2023-04-17", 4 | "version": "0.1", 5 | "description": "chat 聊天 引导助手", 6 | "boot": [{ 7 | "w": "我想让你充当我的朋友 回复1开始", 8 | "p": "chat:我想让你充当我的朋友。 我会告诉你我生活中发生的事情,你会回复一些有帮助和支持的东西来帮助我度过困难时期。 不要写任何解释,只用建议/支持的话回复。 我的第一个请求是“我已经在一个项目上工作了很长时间,现在我遇到了很多挫折,因为我不确定它是否朝着正确的方向发展。请帮助我保持积极并专注于重要的事情 " 9 | }, 10 | { 11 | "w": "{{m1}}", 12 | "r": "r1", 13 | "p": "chat:{{r1}}}", 14 | "b": [1] 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /old/hot.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ruidong", 3 | "date": "2023-04-19", 4 | "version": "0.1", 5 | "description": "查看webfollow最近热门帖子讲了什么", 6 | "boot": [{ 7 | "w": "查看什么主题", 8 | "r": "query", 9 | "p": "spider:https://api.webfollow.cc/api/articles?source=EXPLORE&query={{query}}&size=20&sort=channel,desc::jsonpath=$.content[*]" 10 | }, 11 | { 12 | "p": "len:m0" 13 | }, 14 | { 15 | "p": "len:m0" 16 | }, 17 | { 18 | "w": "{{m2 - m1 + 1}} [{{(m0[m2-m1])['channelName']}}] {{(m0[m2-m1])['title']}}", 19 | "p": "-:m1", 20 | "b": { 21 | "0": 5 22 | } 23 | }, { 24 | "b": [3] 25 | }, { 26 | "w": "请输入编号查看文章", 27 | "r": "r5", 28 | "p": "spider:https://api.webfollow.cc/api/articles/{{m0[(r5|int)-1].id}}::tojson" 29 | }, 30 | { 31 | "p": "html2md:{{m5['description']}}" 32 | }, 33 | { 34 | "w": "## {{m5['title']}} \n * {{m5['channelName']}} {{m5['pubDateTime']}} \n \n {{m6}} \n 查看原文\n ", 35 | "b": [5] 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /old/httpserver.py: -------------------------------------------------------------------------------- 1 | from http.server import SimpleHTTPRequestHandler, HTTPServer 2 | import json 3 | from agent import gpt_agent 4 | from interpreter import handler 5 | from utils.parse import parse 6 | 7 | config = {} 8 | 9 | 10 | class Env: 11 | def __init__(self, bootName, env, index) -> None: 12 | self.bootName = bootName 13 | self.env = env 14 | self.index = index 15 | 16 | 17 | env = Env('', {}, 0) 18 | 19 | 20 | class RequestHandler(SimpleHTTPRequestHandler): 21 | 22 | def _cors_header(self): 23 | self.send_header('Access-Control-Allow-Origin', '*') 24 | self.send_header('Access-Control-Allow-Methods', '*') 25 | self.send_header('Access-Control-Allow-Headers', '*') 26 | 27 | def do_OPTIONS(self): 28 | self.send_response(200) 29 | self._cors_header() 30 | self.end_headers() 31 | 32 | def do_GET(self): 33 | if self.path == '/favicon.ico': 34 | return 35 | self.query = self.path.split('?')[1] 36 | params = parse(self.query, '&') 37 | self.send_response(200) 38 | self.send_header("Content-type", "application/json; charset=utf-8") 39 | self.end_headers() 40 | res = interpreter(params['msg'], env) 41 | data = {'data': res} 42 | self.wfile.write(json.dumps(data, ensure_ascii=False) 43 | .encode('utf-8')) 44 | 45 | def do_POST(self): 46 | self.send_response(200) 47 | self.send_header('Content-type', 'application/json') 48 | self._cors_header() 49 | self.end_headers() 50 | req_datas = self.rfile.read(int(self.headers['content-length'])) 51 | 52 | if self.path.find('/v1/chat/completions') == 0: 53 | req = json.loads(req_datas)['messages'][0]['content'] 54 | res = interpreter(req.replace('\n', ''), env) 55 | # print(len(res)) 56 | if isinstance(res, list): 57 | if len(res) < 3: 58 | res = " \n".join(res) 59 | else: 60 | res = " \n - ".join(res) 61 | res = ' - '+res 62 | data = {"choices": [ 63 | { 64 | "message": { 65 | "role": "assistant", 66 | "content": res 67 | } 68 | }]} 69 | else: 70 | res = interpreter(req_datas['msg'], env) 71 | data = {'data': res} 72 | self.wfile.write(json.dumps(data).encode('utf-8')) 73 | 74 | 75 | def interpreter(msg, env): 76 | # print(bootName, index, env) 77 | if msg == 'exit': 78 | restEnv() 79 | return 'bye!' 80 | elif msg == 'ls': 81 | boots = config.keys() 82 | res = [] 83 | for b in boots: 84 | res.append('{} : {} '.format(b, config[b]['description'])) 85 | return res 86 | elif msg in config: 87 | restEnv() 88 | writer = Writer() 89 | handler(config[msg]['boot'], writer, input=msg, collect=env.env, 90 | interruptRead=True) 91 | env.index = env.env['index'] 92 | env.bootName = msg 93 | if 'exit' in env.env: 94 | bootName = env.bootName 95 | restEnv() 96 | writer.println('bye ' + bootName + '!') 97 | return writer.content 98 | else: 99 | return writer.content 100 | elif env.bootName in config: 101 | writer = Writer() 102 | handler(config[env.bootName]['boot'], writer, env.index, msg, env.env, 103 | skipWR=True, interruptRead=True) 104 | env.index = env.env['index'] 105 | if 'exit' in env.env: 106 | bootName = env.bootName 107 | restEnv() 108 | writer.println('bye ' + bootName + '!') 109 | return writer.content 110 | else: 111 | return writer.content 112 | else: 113 | return gpt_agent(msg) 114 | 115 | 116 | def restEnv(): 117 | env.bootName = '' 118 | env.env = {} 119 | env.index = 0 120 | 121 | 122 | class Writer: 123 | 124 | def __init__(self) -> None: 125 | self.content = [] 126 | 127 | def println(self, o): 128 | if isinstance(o, list): 129 | for i in o: 130 | self.content.append(i) 131 | else: 132 | self.content.append(o) 133 | 134 | def print(self, o): 135 | if isinstance(o, list): 136 | for i in o: 137 | self.content.append(i) 138 | else: 139 | self.content.append(o) 140 | 141 | def readline(self): 142 | return 'hello world' 143 | 144 | 145 | def startserver(config0, port): 146 | global config 147 | config = config0 148 | server = HTTPServer(('0.0.0.0', port), RequestHandler) 149 | print('\n\033[34mBootstrap-GPT server\033[0m v1.0.0 \n') 150 | print('\033[34m➜\033[0m Api: \033[36m\ 151 | http://localhost:{}/v1/chat/completions\033[0m' 152 | .format(port)) 153 | print('\033[34m➜\033[0m Web: \033[36m\ 154 | https://weekendproject.space/chat-gpt-online\033[0m') 155 | print('\n') 156 | server.serve_forever() 157 | -------------------------------------------------------------------------------- /old/httpstream.py: -------------------------------------------------------------------------------- 1 | import json 2 | import time 3 | from flask import Flask, Response, request 4 | from agent import gpt_agent_stream 5 | from interpreter import handler 6 | 7 | 8 | class Env: 9 | def __init__(self, bootName, env, index) -> None: 10 | self.bootName = bootName 11 | self.env = env 12 | self.index = index 13 | 14 | 15 | env = Env('', {}, 0) 16 | app = Flask(__name__) 17 | 18 | 19 | @app.route("/") 20 | def index(): 21 | return "Hello World" 22 | 23 | 24 | @app.route("/v1/models") 25 | def models(): 26 | return { 27 | "object": "list", 28 | "data": [ 29 | { 30 | "id": "gpt-3.5-turbo", 31 | "object": "model", 32 | "created": 1677610602, 33 | "owned_by": "openai", 34 | "permission": [ 35 | { 36 | "id": "modelperm-lZPGJwrxyPjMHAm856z8yLf8", 37 | "object": "model_permission", 38 | "allow_create_engine": False, 39 | "allow_sampling": True, 40 | "allow_logprobs": True, 41 | "allow_search_indices": False, 42 | "allow_view": True, 43 | "allow_fine_tuning": False, 44 | "organization": "*", 45 | "group": None, 46 | "is_blocking": False 47 | } 48 | ], 49 | "root": "gpt-3.5-turbo", 50 | "parent": None 51 | }, 52 | ] 53 | } 54 | 55 | 56 | @app.route("/v1/chat/completions", methods=['GET', 'POST']) 57 | def stream(): 58 | msg = request.args.get('msg') 59 | messages = [] 60 | if not msg: 61 | req = request.get_json() 62 | messages = req['messages'] 63 | msg = messages[len(messages)-1]['content'] 64 | return Response(inter(msg, messages), mimetype="text/event-stream") 65 | 66 | 67 | def interpreter(msg, env, messages=[]): 68 | # print(bootName, index, env) 69 | if msg == 'exit': 70 | restEnv() 71 | return 'bye!' 72 | elif msg == 'ls': 73 | boots = config.keys() 74 | res = [] 75 | for b in boots: 76 | res.append('{} : {} '.format(b, config[b]['description'])) 77 | return res 78 | elif msg in config: 79 | restEnv() 80 | writer = Writer() 81 | handler(config[msg]['boot'], writer, input=msg, collect=env.env, 82 | interruptRead=True) 83 | env.index = env.env['index'] 84 | env.bootName = msg 85 | if 'exit' in env.env: 86 | bootName = env.bootName 87 | restEnv() 88 | writer.println('bye ' + bootName + '!') 89 | return writer.content 90 | else: 91 | return writer.content 92 | elif env.bootName in config: 93 | writer = Writer() 94 | handler(config[env.bootName]['boot'], writer, env.index, msg, env.env, 95 | skipWR=True, interruptRead=True) 96 | env.index = env.env['index'] 97 | if 'exit' in env.env: 98 | bootName = env.bootName 99 | restEnv() 100 | writer.println('bye ' + bootName + '!') 101 | return writer.content 102 | else: 103 | return writer.content 104 | else: 105 | return gpt_agent_stream(msg, messages) 106 | 107 | 108 | def restEnv(): 109 | env.bootName = '' 110 | env.env = {} 111 | env.index = 0 112 | 113 | 114 | class Writer: 115 | 116 | def __init__(self) -> None: 117 | self.content = [] 118 | 119 | def println(self, o): 120 | if isinstance(o, list): 121 | for i in o: 122 | self.content.append(i) 123 | else: 124 | self.content.append(o) 125 | 126 | def print(self, o): 127 | if isinstance(o, list): 128 | for i in o: 129 | self.content.append(i) 130 | else: 131 | self.content.append(o) 132 | 133 | def readline(self): 134 | return 'hello world' 135 | 136 | 137 | def inter(req, messages=[]): 138 | res = interpreter(req, env, messages) 139 | # print(req, res) 140 | if res: 141 | if isinstance(res, list): 142 | if len(res) < 3: 143 | yield warp(" \n".join(res), True) 144 | else: 145 | for i in res: 146 | time.sleep(0.1) 147 | yield warp(' - {} \n'.format(i)) 148 | yield warp(None, True) 149 | elif isinstance(res, str): 150 | yield warp(res, True) 151 | elif isinstance(res, object): 152 | for event in res: 153 | yield json.dumps(event, ensure_ascii=False) 154 | else: 155 | yield warp(res, True) 156 | else: 157 | pass 158 | 159 | 160 | def warp(content, stop=False): 161 | return json.dumps( 162 | obj={"choices": [{"delta": {"content": content}, 163 | "finish_reason": "stop" if stop else None}]}, 164 | ensure_ascii=False 165 | ) 166 | 167 | 168 | def starthttp(config0, port): 169 | global config 170 | config = config0 171 | app.run(port=port) 172 | -------------------------------------------------------------------------------- /old/interpreter.py: -------------------------------------------------------------------------------- 1 | from agent import agent 2 | from utils.templateEngine import render 3 | 4 | 5 | # w:write p:prompt b:branch Array next, Obj switch 6 | def handler(boot, io=None, index=0, input='', collect={}, skipWR=False, 7 | interruptRead=False): 8 | inst = boot[index] 9 | write = inst['w'] if 'w' in inst else None 10 | read = inst['r'] if 'r' in inst else None 11 | prompt = inst['p'] if 'p' in inst else None 12 | branch = inst['b'] if 'b' in inst else None 13 | msg = input 14 | size = len(boot) 15 | 16 | collect['index'] = index 17 | 18 | if not skipWR: 19 | if write: 20 | content = render(write, collect) 21 | collect['w'+str(index)] = content 22 | io.println(content) 23 | else: 24 | pass 25 | 26 | if read: 27 | if interruptRead: 28 | return msg 29 | else: 30 | io.print('\033[34m>\033[0m ') 31 | msg = io.readline() 32 | collect[read] = msg 33 | else: 34 | collect['r'+str(index)] = input 35 | else: 36 | if read: 37 | collect[read] = input 38 | else: 39 | collect['r'+str(index)] = input 40 | 41 | if prompt: 42 | content = render(prompt, collect) 43 | collect['p'+str(index)] = content 44 | msg = agent(content, collect, prompt) 45 | collect['m'+str(index)] = msg 46 | else: 47 | pass 48 | 49 | if branch: 50 | if isinstance(branch, list): 51 | for i in branch: 52 | msg = handler(boot, io, i, msg, collect, False, interruptRead) 53 | elif isinstance(branch, object): 54 | key = str(msg) 55 | if key in branch: 56 | index0 = branch[key] 57 | if int(index0) < 0: 58 | collect['exit'] = True 59 | return key 60 | else: 61 | msg = handler(boot, io, index0, msg, collect, False, 62 | interruptRead) 63 | elif index+1 < size: 64 | msg = handler(boot, io, index+1, msg, collect, False, 65 | interruptRead) 66 | else: 67 | pass 68 | else: 69 | pass 70 | elif index+1 < size: 71 | msg = handler(boot, io, index+1, msg, collect, False, interruptRead) 72 | else: 73 | collect['exit'] = True 74 | return msg 75 | -------------------------------------------------------------------------------- /old/music.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ruidong", 3 | "date": "2023-05-05", 4 | "version": "0.1", 5 | "description": "网易云听歌", 6 | "boot": [{ 7 | "w": "输入网易云歌曲id", 8 | "r": "songid" 9 | }, { 10 | "w": "" 11 | }] 12 | } -------------------------------------------------------------------------------- /old/rss.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ruidong", 3 | "date": "2023-04-19", 4 | "version": "0.1", 5 | "description": "查看rss信息", 6 | "boot": [{ 7 | "w": "查看什么主题", 8 | "r": "query", 9 | "p": "spider:https://api.webfollow.cc/api/channels/ids?search={{query}}::tojson" 10 | }, 11 | { 12 | "p": "spider:https://api.webfollow.cc/api/channels/articles?size=10&id={{m0[0]}}::jsonpath=$.content[*]" 13 | }, 14 | { 15 | "p": "len:m1" 16 | }, 17 | { 18 | "p": "len:m1" 19 | }, 20 | { 21 | "w": "{{m3 - m2 + 1}} [{{(m1[m3-m2])['channelName']}}] {{(m1[m3-m2])['title']}}", 22 | "p": "-:m2", 23 | "b": { 24 | "0": 6 25 | } 26 | }, { 27 | "b": [4] 28 | }, { 29 | "w": "请输入编号查看文章", 30 | "r": "index", 31 | "p": "spider:https://api.webfollow.cc/api/articles/{{m1[(index|int)-1].id}}::tojson" 32 | }, 33 | { 34 | "p": "text-len:{{m6['enclosure']}}", 35 | "b": { 36 | "0": 9 37 | } 38 | }, 39 | { 40 | "w": "## {{m6['title']}} \n * {{m6['channelName']}} {{m6['pubDateTime']}} \n \n {{m6['description']}} \n 查看原文\n ", 41 | "b": [6] 42 | }, 43 | { 44 | "w": "## {{m6['title']}} \n * {{m6['channelName']}} {{m6['pubDateTime']}} \n \n {{m6['description']}} \n 查看原文\n ", 45 | "b": [6] 46 | } 47 | ] 48 | } -------------------------------------------------------------------------------- /old/spider.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ruidong", 3 | "date": "2023-04-17", 4 | "version": "0.1", 5 | "description": "wiki 引导助手", 6 | "boot": [{ 7 | "w": "请输入主题", 8 | "r": "r0", 9 | "p": "spider:https://zh.wikipedia.org/wiki/{{r0}}::select=.infobox" 10 | }, { 11 | "p": "html2md:{{m0[0]}}" 12 | }, { 13 | "w": "{{m1}}" 14 | }] 15 | } -------------------------------------------------------------------------------- /old/summarize.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ruidong", 3 | "date": "2023-04-19", 4 | "version": "0.1", 5 | "description": "总结网页", 6 | "boot": [{ 7 | "w": "请输入网址", 8 | "r": "r0", 9 | "p": "spider:{{r0}}::select=article" 10 | }, { 11 | "p": "chat:总结一下这个页面介绍了什么{{m0}}" 12 | }, { 13 | "w": "总结: {{m1}} \n还要总结其他网页吗? y/n", 14 | "r": "r2", 15 | "b": { 16 | "y": 0, 17 | "n": -1 18 | } 19 | }] 20 | } -------------------------------------------------------------------------------- /old/v2-hot.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ruidong", 3 | "date": "2023-04-19", 4 | "version": "0.1", 5 | "description": "查看v2最近热门帖子讲了什么", 6 | "boot": [{ 7 | "p": "spider:https://api.webfollow.cc/api/channels/articles?query=&page=0&size=20&sort=channel,desc&id=rsshub.app%2Fv2ex%2Ftopics%2Fhot::jsonpath=$.content[*]" 8 | }, 9 | { 10 | "p": "len:m0" 11 | }, 12 | { 13 | "p": "len:m0" 14 | }, 15 | { 16 | "w": "{{m2 - m1 + 1}} {{(m0[m2-m1])['title']}}", 17 | "p": "-:m1", 18 | "b": { 19 | "0": 5 20 | } 21 | }, { 22 | "b": [3] 23 | }, { 24 | "w": "请输入编号查看讲了什么", 25 | "r": "r5", 26 | "p": "spider:https://api.webfollow.cc/api/articles/{{m0[(r5|int)-1].id}}::jsonpath=$.description" 27 | }, 28 | { 29 | "p": "html2md:{{m5[0]}}" 30 | }, 31 | { 32 | "p": "chat:用20字总结一下{{m6}}" 33 | }, { 34 | "w": "{{m6}} \n\n总结:{{m7}}", 35 | "b": [5] 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /old/while.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ruidong", 3 | "date": "2023-04-17", 4 | "version": "0.1", 5 | "description": "循环次数测试", 6 | "boot": [{ 7 | "w": "你想让我循环多少次", 8 | "r": "r0" 9 | }, 10 | { 11 | "w": "确认{{r0}}请按y", 12 | "r": "r1", 13 | "b": { 14 | "y": 2, 15 | "n": 0 16 | } 17 | }, 18 | { 19 | "w": "请输入", 20 | "r": "r2", 21 | "p": "text:{{r2}}" 22 | }, { 23 | "p": "-:r0", 24 | "b": { 25 | "0": -1 26 | } 27 | }, { 28 | "b": [2] 29 | } 30 | ] 31 | } -------------------------------------------------------------------------------- /old/writecode.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "ruidong", 3 | "date": "2023-04-17", 4 | "version": "0.1", 5 | "description": "code boot", 6 | "boot": [{ 7 | "w": "Hello, this is a code template. \nPlease enter the language type", 8 | "r": "language" 9 | }, 10 | { 11 | "w": "Please enter the requirement", 12 | "r": "r2", 13 | "p": "chat:用{{language}} 写一个 {{r2}}" 14 | }, 15 | { 16 | "w": "{{m1}}" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /support/fun/function.py: -------------------------------------------------------------------------------- 1 | from utils.templateEngine import render 2 | from agent import agent 3 | 4 | 5 | def println(bootwarp, instr, interruptRead=False): 6 | r = render(instr.args, bootwarp.env) 7 | if r.find('\\n') > -1: 8 | r = r.replace('\\n', '\n') 9 | if r == '$': 10 | if not interruptRead: 11 | bootwarp.io.print('\033[34m>\033[0m ') 12 | r = bootwarp.io.readline() 13 | else: 14 | pass 15 | if instr.target and instr.target != '$': 16 | bootwarp.env[instr.target] = r 17 | else: 18 | bootwarp.io.println(r) 19 | 20 | 21 | def read(bootwarp, instr, interruptRead=False): 22 | if not interruptRead: 23 | bootwarp.io.print('\033[34m>\033[0m ') 24 | msg = bootwarp.io.readline() 25 | bootwarp.env[instr.args] = msg 26 | 27 | 28 | def jump(bootwarp, instr): 29 | flag = render(instr.args, bootwarp.env).strip() 30 | if flag != 0 and flag != '0' and flag: 31 | label = render(instr.target, bootwarp.env) 32 | if isinstance(label, str): 33 | label = bootwarp.env[label] 34 | else: 35 | pass 36 | index = int(label) 37 | bootwarp.setIndex(index) 38 | else: 39 | pass 40 | 41 | 42 | def label(bootwarp, instr): 43 | # bootwarp.env[instr.args] = bootwarp.index 44 | # print(instr.args, bootwarp.index) 45 | pass 46 | 47 | 48 | def call(bootwarp, instr): 49 | r = render(instr.args, bootwarp.env) 50 | bootwarp.env[instr.target] = agent(r, bootwarp.env, instr.args) 51 | 52 | 53 | def loadFuncs(interruptRead=False) -> dict: 54 | env = {} 55 | env['>'] = lambda bootwarp, instr: println(bootwarp, instr, interruptRead) 56 | env['<'] = lambda bootwarp, instr: read(bootwarp, instr, interruptRead) 57 | env['^'] = jump 58 | env[':'] = label 59 | env['@'] = call 60 | return env 61 | -------------------------------------------------------------------------------- /utils/file.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def listdir(path): 5 | return os.listdir(path) 6 | 7 | 8 | def readfile(filename): 9 | with open(filename, 'r') as file: 10 | return file.read() 11 | -------------------------------------------------------------------------------- /utils/json.py: -------------------------------------------------------------------------------- 1 | import json 2 | from utils.file import readfile 3 | 4 | 5 | def read_file_to_json(filename): 6 | return json.loads(readfile(filename)) 7 | 8 | 9 | def to_obj(str): 10 | return json.loads(str) 11 | -------------------------------------------------------------------------------- /utils/parse.py: -------------------------------------------------------------------------------- 1 | def parse(str, splitKey='\n'): 2 | array = str.split(splitKey) 3 | result = {} 4 | for line in array: 5 | if '=' in line: 6 | kv = line.split('=') 7 | result[kv[0]] = kv[1] 8 | else: 9 | result[line] = None 10 | return result 11 | 12 | 13 | def parseone(str, splitKey='\n'): 14 | i = str.find(splitKey) 15 | result = {} 16 | if i != -1: 17 | result[str[:i]] = str[i+1:] 18 | else: 19 | result[str] = True 20 | return result 21 | -------------------------------------------------------------------------------- /utils/templateEngine.py: -------------------------------------------------------------------------------- 1 | # import re 2 | from jinja2 import Template 3 | 4 | # def render(template, context): 5 | # template_vars = re.findall(r"\{\{\s*([a-zA-Z0-9_]+)\s*\}\}", template) 6 | # temp = template 7 | # for var in template_vars: 8 | # if var in context: 9 | # temp = temp.replace("{{" + var + "}}", str(context[var])) 10 | # else: 11 | # temp = temp.replace("{{" + var + "}}", "") 12 | # return temp 13 | 14 | 15 | def render(template, context): 16 | v = Template(template).render(context) 17 | # print(v) 18 | return v 19 | --------------------------------------------------------------------------------