Image of the Week
This is one of my favourite pictures. It is an unedited snapshot of an unoccupied restaurant.

This is one of my favourite pictures. It is an unedited snapshot of an unoccupied restaurant.

We did the almost-annual unconference, this time at the Saalbau Bornheim. The attendance was expectedly low at 5 persons, one person joining us from Amsterdam and one person joining us from Darmstadt, the rest being Frankfurt.pm regulars.
None of us had prepared anything in a presentation format, with slides, but we had a lot to talk about regarding the use of LLMs and what that means for the economy and also for us personally. I spoke a lot about how I don't see that the AI frontier labs can ever recoup the money they've pledged on datacenters. We also mused about why Chinese labs are giving away their models and also why Mark Zuckerberg is doing the same with Llama-2 and Llama-3. We concluded that this is their strategic approach to prevent a hegemony by the other two frontier labs.
Tech-wise, we looked at some approaches to LLMs. I showed my (yet) unpublished skeleton files for Perl modules and Mojolicious applications. I've found that giving LLMs like GLM-5.3 files to work from tends to prod the model to produce code close to that style. Since I prefer that style to other styles, I've found this approach very successful.
In addition, we also looked at how superpowers works and that a good side benefit of using it is that you get some test files written by the LLM already. We all found that creating test files is a good use of LLMs. Since the code in test files is disposable and if the test file is written in a too complex way, you can just delete it or rewrite it without consequences on the main code.
My main comparison was between the two approaches I'd used for writing two
applications. One application was an extractor that creates CalDAV entries
from a picture of an event poster. I had created that script using GLM-5.3
as a one-shot without superpowers. The resulting code worked, and used GLM-4.6V
to parse the image and create the .ics output. The resulting code also
was very icky to work with, spending far more lines on various configurability
I would never use and precautions against missing tools that would never be
missing.
The other application was a web frontend to the pi agent, to make it more
convenient for me to use LLMs. Using the browser allows me to create fancy
widgets to display the status of the test suite and also submit screenshots
to the LLM for reference. I created this frontend using a relatively detailed
list of features and also described which functionality should be implemented
in what file, providing structure to the LLM. This approach resulted in much
better and much more maintainable code than the one-shot leaving the LLM
to implement things all on its own.
For lunch, we went to a new Chinese-style place with handmade noodles. I had a reasonably priced beef soup with handmade noodles. It was very spicy but otherwise good.
After lunch, we discussed the use of Perl to tie together some tools for language and speech analysis. We looked at how different Chinese is from other languages, and how different Cantonese and Mandarin are.
I was revisiting some old pictures and found this series of pictures shot in the MyZeil shopping mall.

Recently I took up photography again. Or rather, I made more of a conscious effort to take pictures again, as opposed to snapping them. I have my existing image import pipeline, which copies the files from the devices to my central server into timestamped directories.
Recently I actually exhausted the storage of my mobile phone and that made me
realize that I want to run my photo import via rsync from abroad on my phone
instead of local-only copying via mounted drives.
Before the change, the program took all files in the DCIM directory and
copied them via an SMB mount to the central server:
DCIM/Camera directoriesDCIM/Camera/archive as a safety measure. I manually delete the archive/ directory from time to timeBut running the import on a gphoto2 mounted directory does not allow to move transferred files to the DCIM/archive directory.
This would be ameliorated by using rsync. but a more discerning approach is still needed since I might have renamed the target directories
on the central server in the meantime.
The new approach addresses these points
DCIM/Camera directoriesrsyncUsing rsync and always transferring / synchronizing all images makes the transfer resilient against network failures and partial transfers.
Looking at the already existing filenames on the target end also opens the door to reading calendar entries and creating the directories with their calendar entry outright, as I've decoupled the directory name from the image creation timestamp.
ssh remote targetMoving to rsync also enables backing up to a remote machine over ssh. To move the files into the appropriate locations, I also need to read remote directories.
I did not find an established module on CPAN for this. Filesys::Virtual::SSH is OKish, but I don't like the API
of Filesys::Virtual overall. I only needed a single routine to read a remote directory, so I wrote a very simple wrapper:
sub r_readdir($dir, $type="d") {
if( $dir =~ m!^ssh:(?<host>(\w+\@)?[^:]+):(?<path>.*)! ) {
my $p = $-{path}->[0];
my $cmd = "ssh '$-{host}->[0]' 'find \"$p\" -type $type'";
currently("Reading '$p'");
if($verbose) {
$printer->output_permanent($cmd);
}
return map { s!^\Q$p\E[/\\]?!!r }
split /\r?\n/,readpipe( $cmd );
} else {
opendir my $dh, $dir
or die "Can't read '$dir': $!";
return readdir($dh);
}
}
This allows me to keep all filtering local in perl, which is not efficient over the network but highly efficient in protecting me from needing to shell-escape all the commands.
I often end up with directories named 20260417-1603 , which is better than
nothing. But I still would like to know what happened then. Often I have an
entry in my calendar which might be so-and-sos birthday party, or some
conference or whatnot, and having the computer automatically naming the
directory according to the calendar is a nice touch. I've put off this for a
long time, but now I've actually released
Net::CalDAV::FindEntry
to make this convenient:
my @relevant_events = $cal->get_events(
after => $image_timestamp,
before => $image_timestamp,
calendar => 'Corion'
);
# We blindly take the event that started closest before the photo was taken
my ($ev) = sort { $a->{start} cmp $b->{start} } @relevant_events;
if( $ev ) {
$target_directory{ $image } //= "$image_timestamp - $ev->{title}";
}
With that line added, I get conveniently pre-named directory names on the central server. It's still not perfect, as the directory naming needs to respect timezones while the image timestamps are either in a floating timezone or GMT, but this gets me a long step forward in convenience. Also, I need to clean up the titles of the calendar entries to make them suitable as directory names. Originally I thought Text::CleanFragment would be good for this, but it replaces spaces with underscores, which I do not want in the directory names, so I wrote a small ad-hoc sanitizer for that. So there still is work to do in the future.