luogu 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +45 -0
- data/README.md +58 -0
- data/Rakefile +4 -0
- data/exe/luogu +7 -0
- data/lib/luogu/chatgpt.rb +103 -0
- data/lib/luogu/cli.rb +41 -0
- data/lib/luogu/history_queue.rb +31 -0
- data/lib/luogu/init.rb +20 -0
- data/lib/luogu/prompt_parser.rb +64 -0
- data/lib/luogu/version.rb +5 -0
- data/lib/luogu.rb +17 -0
- data/luogu.gemspec +41 -0
- data/sig/luogu.rbs +4 -0
- metadata +108 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0cd2a93255b9c6ed4fe776dab51414384fea23cad8d73c1e407acb5deb9bb382
|
4
|
+
data.tar.gz: e26cdfa7b3e748a580181f6a916a6fd07667fe6b0a3d3c713c454b9584b09eee
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f6ce3327ccd8824a59e5deda151876f1d6fc1b64247c5d5b1140ae4e1fd8455169b8c346f3101304f4b0dd01a5c201b43d5cbb8f322b91ab23a159d6285cf6c3
|
7
|
+
data.tar.gz: 3b6e68d717a10b7ca2feca6cf5b47760e0ab0d672b5cce34883e992a6fffa49caa0a69cd5f36f98cd51c49d1237d76f643f3ca50c241f328f1789ab803ac38ee
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
luogu (0.1.0)
|
5
|
+
dotenv (~> 2.8, >= 2.8.1)
|
6
|
+
ruby-openai (~> 3.7)
|
7
|
+
tty-prompt (~> 0.23.1)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
dotenv (2.8.1)
|
13
|
+
httparty (0.21.0)
|
14
|
+
mini_mime (>= 1.0.0)
|
15
|
+
multi_xml (>= 0.5.2)
|
16
|
+
mini_mime (1.1.2)
|
17
|
+
multi_xml (0.6.0)
|
18
|
+
pastel (0.8.0)
|
19
|
+
tty-color (~> 0.5)
|
20
|
+
rake (13.0.6)
|
21
|
+
ruby-openai (3.7.0)
|
22
|
+
httparty (>= 0.18.1)
|
23
|
+
tty-color (0.6.0)
|
24
|
+
tty-cursor (0.7.1)
|
25
|
+
tty-prompt (0.23.1)
|
26
|
+
pastel (~> 0.8)
|
27
|
+
tty-reader (~> 0.8)
|
28
|
+
tty-reader (0.9.0)
|
29
|
+
tty-cursor (~> 0.7)
|
30
|
+
tty-screen (~> 0.8)
|
31
|
+
wisper (~> 2.0)
|
32
|
+
tty-screen (0.8.1)
|
33
|
+
wisper (2.0.1)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
arm64-darwin-22
|
37
|
+
ruby
|
38
|
+
x86_64-linux
|
39
|
+
|
40
|
+
DEPENDENCIES
|
41
|
+
luogu!
|
42
|
+
rake (~> 13.0)
|
43
|
+
|
44
|
+
BUNDLED WITH
|
45
|
+
2.4.6
|
data/README.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Luogu
|
2
|
+
> 锣鼓,现在的写代码就如古代的求神仪式一样,以前敲锣打鼓求天,现在敲锣打鼓求大模型
|
3
|
+
|
4
|
+
用来开发 prompt 工程的工具
|
5
|
+
|
6
|
+
### 安装
|
7
|
+
- 安装ruby,要求2.6以上,Mac自带不需要再安装
|
8
|
+
- gem install luogu
|
9
|
+
- 如果使用 mac 可能你需要使用sudu权限
|
10
|
+
- 如果需要在终端显示markdown,需要 [glow](https://github.com/charmbracelet/glow)
|
11
|
+
|
12
|
+
### 使用
|
13
|
+
- luogu build <file> 编译成对应的json
|
14
|
+
- luogu run <file> 测试prompt
|
15
|
+
|
16
|
+
你可以在项目目录的.env中设置下面的环境变量,或者直接系统设置
|
17
|
+
```
|
18
|
+
OPENAI_ACCESS_TOKEN=zheshiyigetoken
|
19
|
+
OPENAI_TEMPERATURE=0.7
|
20
|
+
OPENAI_LIMIT_HISTORY=6
|
21
|
+
```
|
22
|
+
|
23
|
+
prompt.md 示例
|
24
|
+
```
|
25
|
+
@s
|
26
|
+
你是一个罗纳尔多的球迷
|
27
|
+
|
28
|
+
@a
|
29
|
+
好的
|
30
|
+
|
31
|
+
@u
|
32
|
+
罗纳尔多是谁?
|
33
|
+
|
34
|
+
@a
|
35
|
+
是大罗,不是C罗
|
36
|
+
```
|
37
|
+
|
38
|
+
如果需要处理历史记录的是否进入上下文可以使用,在 prompt.md写入
|
39
|
+
|
40
|
+
|
41
|
+
@callback
|
42
|
+
```ruby
|
43
|
+
if assistant_message =~ /```ruby/
|
44
|
+
puts "记录本次记录"
|
45
|
+
self.push_history(user_message, assistant_message)
|
46
|
+
else
|
47
|
+
puts "抛弃本次记录"
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
|
52
|
+
### 进入run模式
|
53
|
+
- save 保存对话
|
54
|
+
- row history 查看对话历史
|
55
|
+
- history 查看当前上下文
|
56
|
+
- exit 退出
|
57
|
+
|
58
|
+
## MIT 协议
|
data/Rakefile
ADDED
data/exe/luogu
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
module Luogu
|
2
|
+
class ChatGPT
|
3
|
+
def initialize(file)
|
4
|
+
@temperature = ENV.fetch('OPENAI_TEMPERATURE', '0.7').to_f
|
5
|
+
@limit_history = ENV.fetch('OPENAI_LIMIT_HISTORY', '6').to_i * 2
|
6
|
+
|
7
|
+
@prompt = PromptParser.new(file)
|
8
|
+
@row_history = []
|
9
|
+
@history = HistoryQueue.new @limit_history
|
10
|
+
end
|
11
|
+
|
12
|
+
def request(messages)
|
13
|
+
response = client.chat(
|
14
|
+
parameters: {
|
15
|
+
model: "gpt-3.5-turbo",
|
16
|
+
messages: messages,
|
17
|
+
temperature: 0.7,
|
18
|
+
})
|
19
|
+
response.dig("choices", 0, "message", "content")
|
20
|
+
end
|
21
|
+
|
22
|
+
def chat(user_message)
|
23
|
+
messages = (@prompt.render + @history.to_a) << {role: "user", content: user_message}
|
24
|
+
assistant_message = self.request(messages)
|
25
|
+
|
26
|
+
self.push_row_history(user_message, assistant_message)
|
27
|
+
|
28
|
+
if @prompt.ruby_code
|
29
|
+
puts "执行文档中的callback"
|
30
|
+
instance_eval @prompt.ruby_code, @prompt.file_path, @prompt.ruby_code_line
|
31
|
+
else
|
32
|
+
puts "执行默认的历史记录"
|
33
|
+
self.push_history(user_message, assistant_message)
|
34
|
+
end
|
35
|
+
|
36
|
+
assistant_message
|
37
|
+
end
|
38
|
+
|
39
|
+
def push_row_history(user_message, assistant_message)
|
40
|
+
@row_history << {role: "user", content: user_message}
|
41
|
+
@row_history << {role: "assistant", content: assistant_message}
|
42
|
+
end
|
43
|
+
|
44
|
+
def push_history(user_message, assistant_message)
|
45
|
+
@history.enqueue({role: "user", content: user_message})
|
46
|
+
@history.enqueue({role: "assistant", content: assistant_message})
|
47
|
+
end
|
48
|
+
|
49
|
+
def ask(message)
|
50
|
+
TTY::Prompt.new.ask(message)
|
51
|
+
end
|
52
|
+
|
53
|
+
def puts(message)
|
54
|
+
@_puts_method ||= if system("which glow > /dev/null 2>&1")
|
55
|
+
require 'shellwords'
|
56
|
+
-> (message) {
|
57
|
+
system("echo #{Shellwords.escape(message)} | glow -")
|
58
|
+
}
|
59
|
+
else
|
60
|
+
-> (message) { puts message }
|
61
|
+
end
|
62
|
+
@_puts_method.call message
|
63
|
+
end
|
64
|
+
|
65
|
+
def save(history, file_path)
|
66
|
+
text = ""
|
67
|
+
role_map = {"user" => "@u", "assistant" => "@a", "system" => "@s"}
|
68
|
+
history.each do |item|
|
69
|
+
text += role_map[item[:role]]
|
70
|
+
text += "\n"
|
71
|
+
text += item[:content]
|
72
|
+
text += "\n\n"
|
73
|
+
end
|
74
|
+
File.open(file_path, 'w') do |f|
|
75
|
+
f.write(text)
|
76
|
+
end
|
77
|
+
puts "已经保存文件到 #{file_path}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def run
|
81
|
+
loop do
|
82
|
+
# 从命令行读取输入
|
83
|
+
input = self.ask("请输入你的指令>").cover_chinese
|
84
|
+
|
85
|
+
# 根据用户输入执行相应的操作
|
86
|
+
case input
|
87
|
+
when "save"
|
88
|
+
self.save @row_history, "./prompt.row_history.md"
|
89
|
+
self.save @history.to_a, "./prompt.history.md"
|
90
|
+
when "row history"
|
91
|
+
p @row_history
|
92
|
+
when "history"
|
93
|
+
p @history.to_a
|
94
|
+
when "exit"
|
95
|
+
puts "再见!"
|
96
|
+
break
|
97
|
+
else
|
98
|
+
self.puts self.chat(input)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/luogu/cli.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module Luogu
|
2
|
+
module_function
|
3
|
+
def cli
|
4
|
+
options = {}
|
5
|
+
subcommands = {}
|
6
|
+
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: luogu [command]"
|
9
|
+
|
10
|
+
opts.on("-h", "--help", "Prints help") do
|
11
|
+
puts """
|
12
|
+
luogu build <file> -> 编译prompt
|
13
|
+
luogu run <file> -> 测试 prompt
|
14
|
+
"""
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
|
18
|
+
end.parse!
|
19
|
+
|
20
|
+
|
21
|
+
subcommands['build'] = Proc.new do |args|
|
22
|
+
data = PromptParser.new(args.first).to_json
|
23
|
+
target_path = args[1] || "./prompt.json"
|
24
|
+
File.open(target_path, 'w') do |f|
|
25
|
+
f.write(data)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
subcommands['run'] = Proc.new do |args|
|
30
|
+
chatgpt = ChatGPT.new(args.first)
|
31
|
+
chatgpt.run
|
32
|
+
end
|
33
|
+
|
34
|
+
if subcommands.key?(ARGV.first)
|
35
|
+
subcommands[ARGV.first].call(ARGV[1..-1])
|
36
|
+
else
|
37
|
+
puts "Invalid command. Use -h or --help for usage information."
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Luogu
|
2
|
+
class HistoryQueue
|
3
|
+
def initialize(max_size = 12)
|
4
|
+
@queue = []
|
5
|
+
@max_size = max_size
|
6
|
+
end
|
7
|
+
|
8
|
+
def enqueue(element)
|
9
|
+
if @queue.size == @max_size
|
10
|
+
@queue.shift
|
11
|
+
end
|
12
|
+
@queue << element
|
13
|
+
end
|
14
|
+
|
15
|
+
def dequeue
|
16
|
+
@queue.shift
|
17
|
+
end
|
18
|
+
|
19
|
+
def size
|
20
|
+
@queue.size
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_a
|
24
|
+
@queue
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_json
|
28
|
+
JSON.pretty_generate @queue
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/luogu/init.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "openai"
|
2
|
+
require 'dotenv/load'
|
3
|
+
require "tty-prompt"
|
4
|
+
require 'json'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
require_relative 'history_queue'
|
8
|
+
require_relative "prompt_parser"
|
9
|
+
require_relative "chatgpt"
|
10
|
+
require_relative "cli"
|
11
|
+
|
12
|
+
def client
|
13
|
+
$client ||= OpenAI::Client.new
|
14
|
+
end
|
15
|
+
|
16
|
+
class String
|
17
|
+
def cover_chinese
|
18
|
+
self.gsub(/[\uFF01-\uFF0F]/) {|s| (s.ord-65248).chr}
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Luogu
|
2
|
+
class PromptParser
|
3
|
+
attr_reader :ruby_code, :ruby_code_line, :file_path
|
4
|
+
def initialize(file_path)
|
5
|
+
@file_path = file_path
|
6
|
+
@messages = []
|
7
|
+
@ruby_code = nil
|
8
|
+
@ruby_code_line = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def render
|
12
|
+
process_file
|
13
|
+
if @messages.length.even?
|
14
|
+
@messages
|
15
|
+
else
|
16
|
+
raise "prompt里面的问答对不对, 必须是一问一答, 当前存在单一问题或者答案"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_json
|
21
|
+
JSON.pretty_generate self.render
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def process_file
|
26
|
+
@messages = []
|
27
|
+
file = File.read(@file_path)
|
28
|
+
|
29
|
+
if file =~ /@callback/
|
30
|
+
callback_regex = /@callback\n```ruby\n(.*?)\n```/m
|
31
|
+
@ruby_code = file[callback_regex, 1]
|
32
|
+
@ruby_code_line = self.find_line_number(file, "@callback") + 2
|
33
|
+
file = file.gsub(callback_regex, '')
|
34
|
+
end
|
35
|
+
|
36
|
+
file.split(/(?=@u|@a|@s)/).reject(&:empty?).each do |c|
|
37
|
+
role = if c =~ /^@s/
|
38
|
+
"system"
|
39
|
+
elsif c =~ /^@u/
|
40
|
+
"user"
|
41
|
+
elsif c =~ /^@a/
|
42
|
+
"assistant"
|
43
|
+
end
|
44
|
+
content = c.sub(/^@(u|a|s)\s+/, '').strip
|
45
|
+
@messages << {role: role, content: content}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def find_line_number(text, search_str)
|
50
|
+
lines = text.split("\n")
|
51
|
+
line_number = nil
|
52
|
+
|
53
|
+
lines.each_with_index do |line, index|
|
54
|
+
if line.include?(search_str)
|
55
|
+
line_number = index + 1
|
56
|
+
break
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
line_number
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
data/lib/luogu.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "luogu/version"
|
4
|
+
require_relative "luogu/init"
|
5
|
+
|
6
|
+
module Luogu
|
7
|
+
class Error < StandardError; end
|
8
|
+
# Your code goes here...
|
9
|
+
|
10
|
+
module_eval do
|
11
|
+
Dotenv.load
|
12
|
+
|
13
|
+
OpenAI.configure do |config|
|
14
|
+
config.access_token = ENV.fetch('OPENAI_ACCESS_TOKEN')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/luogu.gemspec
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/luogu/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "luogu"
|
7
|
+
spec.version = Luogu::VERSION
|
8
|
+
spec.authors = ["MJ"]
|
9
|
+
spec.email = ["tywf91@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "luogu 用于 Prompt 工程开发"
|
12
|
+
spec.description = "使用markdown来快速实现 Prompt工程研发"
|
13
|
+
spec.homepage = "https://github.com/mjason/luogu"
|
14
|
+
spec.required_ruby_version = ">= 2.6.0"
|
15
|
+
|
16
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
17
|
+
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
spec.metadata["source_code_uri"] = "https://github.com/mjason/luogu"
|
20
|
+
spec.metadata["changelog_uri"] = "https://github.com/mjason/luogu"
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
spec.files = Dir.chdir(__dir__) do
|
25
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
26
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
spec.bindir = "exe"
|
30
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
31
|
+
spec.require_paths = ["lib"]
|
32
|
+
|
33
|
+
# Uncomment to register a new dependency of your gem
|
34
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
35
|
+
spec.add_dependency 'ruby-openai', '~> 3.7'
|
36
|
+
spec.add_dependency 'dotenv', '~> 2.8', '>= 2.8.1'
|
37
|
+
spec.add_dependency 'tty-prompt', '~> 0.23.1'
|
38
|
+
|
39
|
+
# For more information and examples about making a new gem, check out our
|
40
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
41
|
+
end
|
data/sig/luogu.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: luogu
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- MJ
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-04-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ruby-openai
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dotenv
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.8'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 2.8.1
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '2.8'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.8.1
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: tty-prompt
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.23.1
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 0.23.1
|
61
|
+
description: 使用markdown来快速实现 Prompt工程研发
|
62
|
+
email:
|
63
|
+
- tywf91@gmail.com
|
64
|
+
executables:
|
65
|
+
- luogu
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- Gemfile
|
70
|
+
- Gemfile.lock
|
71
|
+
- README.md
|
72
|
+
- Rakefile
|
73
|
+
- exe/luogu
|
74
|
+
- lib/luogu.rb
|
75
|
+
- lib/luogu/chatgpt.rb
|
76
|
+
- lib/luogu/cli.rb
|
77
|
+
- lib/luogu/history_queue.rb
|
78
|
+
- lib/luogu/init.rb
|
79
|
+
- lib/luogu/prompt_parser.rb
|
80
|
+
- lib/luogu/version.rb
|
81
|
+
- luogu.gemspec
|
82
|
+
- sig/luogu.rbs
|
83
|
+
homepage: https://github.com/mjason/luogu
|
84
|
+
licenses: []
|
85
|
+
metadata:
|
86
|
+
homepage_uri: https://github.com/mjason/luogu
|
87
|
+
source_code_uri: https://github.com/mjason/luogu
|
88
|
+
changelog_uri: https://github.com/mjason/luogu
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 2.6.0
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubygems_version: 3.4.6
|
105
|
+
signing_key:
|
106
|
+
specification_version: 4
|
107
|
+
summary: luogu 用于 Prompt 工程开发
|
108
|
+
test_files: []
|