luogu 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in luogu.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
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
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
data/exe/luogu ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require_relative "../lib/luogu"
6
+
7
+ Luogu.cli
@@ -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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Luogu
4
+ VERSION = "0.1.0"
5
+ 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
@@ -0,0 +1,4 @@
1
+ module Luogu
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
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: []