├── .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 | 
6 | 
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 | 
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 |
--------------------------------------------------------------------------------