Module: Legion::Notebook::Generator
- Defined in:
- lib/legion/notebook/generator.rb
Constant Summary collapse
- NOTEBOOK_TEMPLATE =
{ 'nbformat' => 4, 'nbformat_minor' => 5, 'metadata' => { 'kernelspec' => { 'display_name' => 'Python 3', 'language' => 'python', 'name' => 'python3' }, 'language_info' => { 'name' => 'python' } }, 'cells' => [] }.freeze
Class Method Summary collapse
- .build_prompt(description, kernel) ⇒ Object
- .call_llm(prompt, model: nil, provider: nil) ⇒ Object
- .generate(description:, kernel: 'python3', model: nil, provider: nil) ⇒ Object
- .parse_notebook_response(response) ⇒ Object
- .validate_notebook!(data) ⇒ Object
- .write(path, notebook_data) ⇒ Object
Class Method Details
.build_prompt(description, kernel) ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/legion/notebook/generator.rb', line 36 def self.build_prompt(description, kernel) <<~PROMPT Generate a Jupyter notebook as valid JSON (.ipynb format) for the following task: #{description} Requirements: - Use kernel: #{kernel} - Include a markdown cell with a title and description at the top - Include well-commented code cells - Include markdown explanation cells between code sections - Return ONLY the raw JSON, no markdown fences, no explanation The JSON must follow the .ipynb format with these top-level keys: nbformat, nbformat_minor, metadata, cells Each cell must have: cell_type, metadata, source (array of strings), outputs (array), execution_count PROMPT end |
.call_llm(prompt, model: nil, provider: nil) ⇒ Object
56 57 58 59 60 61 |
# File 'lib/legion/notebook/generator.rb', line 56 def self.call_llm(prompt, model: nil, provider: nil) kwargs = { messages: [{ role: 'user', content: prompt }] } kwargs[:model] = model if model kwargs[:provider] = provider.to_sym if provider Legion::LLM.chat(**kwargs, caller: { source: 'cli', command: 'notebook' }) end |
.generate(description:, kernel: 'python3', model: nil, provider: nil) ⇒ Object
24 25 26 27 28 29 30 |
# File 'lib/legion/notebook/generator.rb', line 24 def self.generate(description:, kernel: 'python3', model: nil, provider: nil) raise ArgumentError, 'legion-llm is required for notebook generation' unless defined?(Legion::LLM) prompt = build_prompt(description, kernel) response = call_llm(prompt, model: model, provider: provider) parse_notebook_response(response) end |
.parse_notebook_response(response) ⇒ Object
63 64 65 66 67 68 69 70 71 72 |
# File 'lib/legion/notebook/generator.rb', line 63 def self.parse_notebook_response(response) content = response[:content].to_s.strip # Strip markdown fences if the LLM wrapped the JSON content = content.gsub(/\A```(?:json)?\n?/, '').gsub(/\n?```\z/, '').strip data = ::JSON.parse(content) validate_notebook!(data) data rescue ::JSON::ParserError => e raise ArgumentError, "LLM returned invalid JSON: #{e.}" end |
.validate_notebook!(data) ⇒ Object
74 75 76 77 78 |
# File 'lib/legion/notebook/generator.rb', line 74 def self.validate_notebook!(data) raise ArgumentError, 'Missing nbformat key' unless data.key?('nbformat') raise ArgumentError, 'Missing cells key' unless data.key?('cells') raise ArgumentError, 'cells must be an array' unless data['cells'].is_a?(Array) end |
.write(path, notebook_data) ⇒ Object
32 33 34 |
# File 'lib/legion/notebook/generator.rb', line 32 def self.write(path, notebook_data) File.write(path, ::JSON.pretty_generate(notebook_data)) end |