Hello. I had an idea to create a tool for generating a library with questions. I think itβs quite useful and much more practical than the AI Course Builder (although that tool is also very cool).
braden
(Braden MacDonald (OpenCraft) - opencraft.com/help)
June 18, 2025, 5:35pm
2
The new libraries (beta) features do not yet have an import-export feature, but itβs being planned at the moment, and I believe the goal is to have some version of it working in the next release (βUlmoβ). CC @jmakowski
In the meantime, you can use the Library Blocks API and XBlock API to generate content from python, move it around among libraries, and export it to OLX.
1 Like
dave
(Dave Ormsbee)
June 18, 2025, 8:56pm
3
FWIW, the work to add import/export functionality to beta libraries is kicking off next week Wednesday, starting with this ticket:
opened 06:37PM - 07 Jun 25 UTC
arch
## Requirements
* Should be able to copy a library to a new instance so that it⦠can be hooked up with a course that uses it.
* Human readable
* Extensible, i.e. new apps/models should be able to hook into it
* Useful for debugging purposes
## Non-requirements
* No need for partial import. This is "wipe everything and make this the new state of things". This is also not going to be permission aware--it's an admin task.
Weirdly enough, this might be a really harsh way to prune a library without breaking dependent content, though it would break all ownership information, unless we add support for that later.
## Tentative Task Breakdown (WIP)
- [ ] Create dump management command as part of Learning Core, i.e. openedx-learning.
This would just dump metadata about the top level learning package into a .toml file in a zip archive.
- [ ] Create restore management command as part of Learning Core, i.e. openedx-learning.
This would just load metadata about the top level learning package into a .toml file in a zip archive.
- [ ] Add support for exporting PublishableEntities
- [ ] Add support for versions export, including draft and published pointers
- [ ] Add support for components, including files
- [ ] Add support for units (and containers as part of that)
- [ ] Refactor to accommodate arbitrary extension
- [ ] Add support for subsections
- [ ] Add support for sections
## Initial thoughts
### TOML for Metadata
As a file format, TOML has some useful attributes:
1. Table formatting makes it easy to break things into sections by app/model.
2. It supports comments, so we can annotate things that are useful as debug data on export, but that might not apply to import, e.g. derived data, creation times, etc.
YAML is another possibility. YAML would scale better to deeply nested structures, and we could make use of separate documents in the same file to separate apps/models that want to attach data. I prefer to start with TOML because it's simpler and won't do weird auto-parsing, e.g. "owner: edx" works fine, but "owner: 2u" dies because it auto-casts the former to a string but the latter looks like it's a failed number to the parser; or "country: US" works fine as a string but "country: NO" turns into a boolean.
### Zip as the archive format
Zip is better supported and more understandable for the average user. The downside is that for repeated assets, Zip is likely to be less efficient overall, particularly if we get many versions of the same component with matching assets. That's not an intended use case for this though, since we only plan to capture draft + publishing versions + whatever versions are pinned by containers, whenever we start supporting that as a feature.
We can do all the operations inside a Zip file directly instead of writing a bunch of files and zipping it later.
### Structure
Let's say we have a library `lib:Axim:2025-06-04`
An example hierarchy could be:
```
Axim2025-06-04.zip
βββ Axim2025-06-04
βββ collections
β βββ interesting-things.toml
βββ entities
β βββ fun-unit-36c349
β β βββ versions
β β βββ 1.toml
β βββ fun-unit-36c349.toml
β βββ xblock.v1
β βββ html
β βββ i-dont-like-the-sidebar-aa1645ade4a7
β β βββ versions
β β βββ 3
β β β βββ block.xml
β β β βββ static
β β βββ 3.toml
β βββ i-dont-like-the-sidebar-aa1645ade4a7.toml
βββ library.toml
```
Some notes:
1. Components have colons in their publishable entity keys, so we make those into directory breaks instead.
2. Versions are currently broken out into their own TOML files in this scenario, but they could also be folded into the TOML file of the entities themselves as a separate section.
The TOML files would be broken up by model/app, like this for a unit version:
```toml
[version]
title = "Fun Unit"
uuid = "a6f97e8e-98b8-4cd9-9dcc-5a6744110401"
[container-version]
children = [
"xblock.v1:html:i-dont-like-the-sidebar-aa1645ade4a7",
# We can mix types in a TOML array, so we can keep the string for the simple
# common use case, but later add entries that are inline tables if we need
# to override things, like:
# {"key" = "xblock.v1:html:i-dont-like-the-sidebar-aa1645ade4a7", "version_num" = 2}
]
[unit-version]
# we wouldn't actually do this, but I'm making an example here...
graded = true
```
Future extensions would add their own tables here.
The actual OLX and static assets for a component go in a subdirectory for the version.
A quick sketch with some comments added:
[Axim2025-06-04.zip](https://github.com/user-attachments/files/20640374/Axim2025-06-04.zip)
If youβre just starting down this road, the part that I would recommend focusing on is the accurate generation of problem OLX content. In the past, Iβve seen LLMs generate OLX that looks plausible at first glance, but turned out to be malformed in subtle ways.
2 Likes