Class: Luogu::ChatLLM

Inherits:
Base
  • Object
show all
Defined in:
lib/luogu/chatllm.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#config, #logger

Constructor Details

#initialize(file, history_path = '.', plugin_file_path = nil) ⇒ ChatLLM

Returns a new instance of ChatLLM.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/luogu/chatllm.rb', line 20

def initialize(file, history_path='.', plugin_file_path=nil)
  @plugin_file_path = plugin_file_path || file.sub(File.extname(file), ".plugin.rb")
  if File.exist?(@plugin_file_path)
    @plugin = Plugin.new(@plugin_file_path).load()
  else
    @plugin = Plugin.new(@plugin_file_path)
  end
  @history_path = history_path
  @prompt_file = file
  @prompt = PromptParser.new(file)
  @row_history = []
  @histories = HistoryQueue.new provider.history_limit

  @request_params = provider.parameter_model.call

  @context = OpenStruct.new

  run_plugin :setup
end

Instance Attribute Details

#contextObject

Returns the value of attribute context.



17
18
19
# File 'lib/luogu/chatllm.rb', line 17

def context
  @context
end

#pluginObject (readonly)

Returns the value of attribute plugin.



18
19
20
# File 'lib/luogu/chatllm.rb', line 18

def plugin
  @plugin
end

Class Method Details

.save(history, file_path) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/luogu/chatllm.rb', line 169

def save(history, file_path)
  text = ""
  role_map = {"user" => "@u", "assistant" => "@a", "system" => "@s"}
  history.each do |item|
    text += role_map[item[:role]]
    text += "\n"
    text += item[:content]
    text += "\n\n"
  end
  FileUtils.mkdir_p(File.dirname(file_path))
  File.open(file_path, 'w') do |f|
    f.write(text)
  end
  puts "已经保存文件到 #{file_path}"
end

Instance Method Details

#ask(message) ⇒ Object



110
111
112
# File 'lib/luogu/chatllm.rb', line 110

def ask(message)
  TTY::Prompt.new.ask(message)
end

#chat(user_message) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/luogu/chatllm.rb', line 63

def chat(user_message)
  @context.user_input = user_message
  run_plugin :before_input do |context|
    user_message = context.user_input
  end

  messages = (@prompt.render + @histories.to_a) << { role: "user", content: user_message}
  run_plugin :after_input do
    messages = @context.request_messages
  end
  assistant_message = request(messages)
  
  self.push_row_history(user_message, assistant_message)

  if @prompt.ruby_code
    puts "执行文档中的callback"
    instance_eval @prompt.ruby_code, @prompt.file_path, @prompt.ruby_code_line
  elsif @plugin.before_save_history_proc
    @context.user_input = user_message
    @context.response_message = assistant_message

    run_plugin :before_save_history
  else
    puts "执行默认的历史记录"
    self.push_history(user_message, assistant_message)
  end

  run_plugin :after_save_history

  assistant_message
end

#playload(messages) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/luogu/chatllm.rb', line 153

def playload(messages)
  messages.each do |message|
    time = Benchmark.measure do
      puts "test: #{message}"
      self.puts self.chat(message)
    end
    puts "test: #{message} 执行时间为 #{time.real}"
  end
  now = Time.now.to_i
  file_name = File.basename(@prompt_file, ".*")

  self.class.save @row_history, File.join(@history_path, "#{file_name}-#{now}.row_history.md")
  self.class.save @histories.to_a, File.join(@history_path, "#{file_name}-#{now}.history.md")
end

#providerObject



44
45
46
# File 'lib/luogu/chatllm.rb', line 44

def provider
  config.provider
end

#push_history(user_message, assistant_message) ⇒ Object



100
101
102
103
104
105
106
107
108
# File 'lib/luogu/chatllm.rb', line 100

def push_history(user_message, assistant_message)
  @histories.enqueue({ role: "user", content: user_message})
  @histories.enqueue({ role: "assistant", content: assistant_message})
  if @plugin.after_save_history_proc
    @context.user_input = user_message
    @context.response_message = response_message
    @plugin.after_save_history_proc.call(self, @context) 
  end
end

#push_row_history(user_message, assistant_message) ⇒ Object



95
96
97
98
# File 'lib/luogu/chatllm.rb', line 95

def push_row_history(user_message, assistant_message)
  @row_history << {role: "user", content: user_message}
  @row_history << {role: "assistant", content: assistant_message}
end

#puts(message) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
# File 'lib/luogu/chatllm.rb', line 114

def puts(message)
  @_puts_method ||= if system("which glow > /dev/null 2>&1")
    require 'shellwords'   
    -> (message) {
      system("echo #{Shellwords.escape(message)} | glow -") 
    }
  else
    -> (message) { puts message }
  end
  @_puts_method.call message
end

#request(messages) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/luogu/chatllm.rb', line 48

def request(messages)
  @request_params.messages = messages
  @context.request_params = @request_params
  run_plugin :before_request
  response = provider.request.call(@request_params.to_h)
  unless response.code == 200
    logger.error response.body.to_s
    raise RequestError
  end
  @context.response = response
  run_plugin :after_request

  provider.parse.call(response)
end

#runObject



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/luogu/chatllm.rb', line 126

def run
  loop do
    # 从命令行读取输入
    input = self.ask("请输入你的指令>").cover_chinese
  
    # 根据用户输入执行相应的操作
    case input
    when "save"
      file_name = File.basename(@prompt_file, ".*")
      self.class.save @row_history, File.join(@history_path, "#{file_name}.row_history.md")
      self.class.save @histories.to_a, File.join(@history_path, "#{file_name}.history.md")
    when "row history"
      p @row_history
    when "history"
      p @histories.to_a
    when "exit"
      puts "再见!"
      break
    else
      time = Benchmark.measure do
        self.puts self.chat(input)
      end
      puts "input: #{input} 执行时间为 #{time.real}"
    end
  end
end

#run_plugin(method_name, &block) ⇒ Object



40
41
42
# File 'lib/luogu/chatllm.rb', line 40

def run_plugin(method_name, &block)
  plugin.run method_name: method_name, llm: self, context: @context, &block
end