Stable DiffusionをWSL上のUbuntu22.04で動かす

環境

Windows 11
WLS2
Ubuntu 22.04
Python 3.10.4

Hugging Faceのアカウント作成

Hugging Faceのアカウント作成し、Tokenを取得する。ユーザーの設定画面のAccess Tokenを開き、New tokenをクリックしてTokenを作成する。後で使用するためコピーしておく。※Email認証がまだの場合はボタンが非活性になっているので注意

作成時の名前は適当で良い。

インストール

pip install diffusers==0.2.4 transformers scipy ftfy

実行

下記の通り実行し、Tokenを入力する。

$ huggingface-cli login

        _|    _|  _|    _|    _|_|_|    _|_|_|  _|_|_|  _|      _|    _|_|_|      _|_|_|_|    _|_|      _|_|_|  _|_|_|_|
        _|    _|  _|    _|  _|        _|          _|    _|_|    _|  _|            _|        _|    _|  _|        _|
        _|_|_|_|  _|    _|  _|  _|_|  _|  _|_|    _|    _|  _|  _|  _|  _|_|      _|_|_|    _|_|_|_|  _|        _|_|_|
        _|    _|  _|    _|  _|    _|  _|    _|    _|    _|    _|_|  _|    _|      _|        _|    _|  _|        _|
        _|    _|    _|_|      _|_|_|    _|_|_|  _|_|_|  _|      _|    _|_|_|      _|        _|    _|    _|_|_|  _|_|_|_|

        To login, `huggingface_hub` now requires a token generated from https://huggingface.co/settings/tokens .
        
Token: 
Login successful
Your token has been saved to /home/ユーザーID/.huggingface/token

Hugging Faceにログインし、以下のページにアクセスして、Access repositoryをクリックする。
https://huggingface.co/CompVis/stable-diffusion-v1-4

cudaの設定が面倒なので、今回はcudaなしで実行する。

from diffusers import StableDiffusionPipeline

pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4", use_auth_token=True)

prompt = "a photograph of an astronaut riding a horse"

image = pipe(prompt)["sample"][0]

image.save("horse.png")

image

実行結果

Hibernate Search 6でFacetを作成したい

初めに

Hibernate Searchを使用して、キーワードに登場する単語の回数を集計したい。※例)残酷な描写あり: 873, 異世界: 481, ハーレム: 471

Hibernate 5まではFacet専用の機能が実装されていたのだが、Hibernate 6からはAggregation機能が実装され、より一般的な集計処理となった。

実装例

集計を実施したいエンティティの変数に下記のようにアノテーションを追加する。

@KeywordField(name = "keyword_facet", aggregable = Aggregable.YES)

集計処理

@Transactional
public Map<String, Long> aggregateByKeywords() {
    AggregationKey<Map<String, Long>> countsByKeywordKey = AggregationKey.of("countsByKeyword");

    return Search.session(entityManager)
            .search(Novel.class) // エンティティ
            .where(f -> f.matchAll()) // 全検索
            .aggregation(countsByKeywordKey, f -> f.terms()
                    .field("keyword_facet", String.class)
                    .maxTermCount(10)) // 登場回数の多い順10件まで
            .fetch(10)
            .aggregation(countsByKeywordKey);
}

集計結果

Mapにキーワードとその文字の登場回数が設定されているので、Loop処理等で展開する。以下はVueの実装例。

<span v-for="(value, name, index) in aggregateByKeywords" :key="index">
    <span v-if="index > 0">, </span>
    {{ name }}: {{ value }}
</span>

R15: 1074, 残酷な描写あり: 873, 異世界: 481, ハーレム: 471, ファンタジー: 451, 異世界転移: 389, チート: 378, 魔法: 362, 冒険: 319, 主人公最強: 296

Hibernate ORMとHibernate Searchで検索結果をソートする

備忘録として、いくつかの実装例を記載しておく。

Hibernate ORMのソート(Spring Data JPAを使用する)

Spring Bootを使用していなくても、下記のように依存関係を読み込むことでSpring Data JPAを使用できる。

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jpa</artifactId>
    <version>${spring-data.version}</version>
</dependency>

クエリメソッドを使用する

ルールに沿ったメソッド名を使用することにより、自動的にHibernateへSQLが発行される。

public interface CrudRepository<T, ID> extends Repository<T, ID> {
    // 登録、または更新
    <S extends T> S save(S entity);      
    // プライマリーキーで検索
    Optional<T> findById(ID primaryKey); 
    // 全検索
    Iterable<T> findAll();               
    // 全件数
    long count();                        
    // 削除
    void delete(T entity);               
    // 存在チェック
    boolean existsById(ID primaryKey); 

例えば、小説データを全検索して、小説のタイトルでソートをかけたい場合、下記のように書く。複数のソート条件を指定する場合は続けて記載する。

@Repository
public interface NovelRepository extends JpaRepository<Novel, Long>, JpaSpecificationExecutor<Novel> {
    List<Novel> findAllByOrderByTitle();
}

※「findAll」の後に余分な「By」があるのは、ルール的にそこに検索条件が入ることになるため、今回は全検索なので「By」だけが残っている。

条件 APIを使用する

criteria を記述することにより、クエリの where 句を定義している場合、ソートは以下のように定義する。複数のソート条件を指定する場合は引数を追加する。

novelRepository.findAll(spec, JpaSort.by("title"))
@Repository
public interface NovelRepository extends JpaSpecificationExecutor<Novel> {
}

Hibernate Searchのソート

ソートの処理実装前に、エンティティに@KeywordFieldを追記する必要がある。

    /** タイトル */
    @FullTextField(analyzer = "japanese")
    @KeywordField(name = "titleSort", sortable = Sortable.YES)
    private String title;

検索時に上記で定義した名称をソート条件に指定する。

import org.hibernate.search.mapper.orm.Search;

@Service
public class NovelService {
    private final EntityManager entityManager;

    @Transactional
    public List<Novel> findAllIndex() {
        return Search.session(entityManager)
                .search(Novel.class)
                .where(f -> f.matchAll())
                .sort(f -> f.field("titleSort"))
                .fetchAllHits();
    }

ソートの条件を指定していないときは、スコアの高い順にソートされている。大雑把に言えば、スコアが高いほど、より多くの述語にマッチしているか、より良くマッチしていることを意味する。そのため、Hibernate Searchに関しては明示的にソートの条件を指定しない方が、良いのかもしれない。

Vue3でvue-i18nの初期化でエラーになる

以下のようなエラーが出ていた。

Uncaught (in promise) SyntaxError: Not available in legacy mode
    at createCompileError (message-compiler.esm-bundler.js?965a:54:1)
    at createI18nError (vue-i18n.esm-bundler.js?666d:100:1)
    at useI18n (vue-i18n.esm-bundler.js?666d:2228:1)
    at setup (NovelSearch.vue?0b40:12:1)
    at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:155:1)
    at setupStatefulComponent (runtime-core.esm-bundler.js?d2dd:7165:1)
    at setupComponent (runtime-core.esm-bundler.js?d2dd:7119:1)
    at mountComponent (runtime-core.esm-bundler.js?d2dd:5473:1)
    at processComponent (runtime-core.esm-bundler.js?d2dd:5448:1)
    at patch (runtime-core.esm-bundler.js?d2dd:5038:1)

Vue 3のsetupでuseI18nを構成する場合は、createI18nのlegacyオプションをfalseに設定する必要がある。

const i18n = createI18n({
  legacy: false, // you must set `false`, to use Composition API
  locale: 'ja',
  messages: {
    en: enNames,
    ja: jaNames
  }
});

const app = createApp(App)
app.use(i18n)
app.mount('#app')

参考:https://vue-i18n.intlify.dev/guide/advanced/composition.html

Eclipseで特定のWarningを非表示にしたい

現象

Eclipseでは属性名の間違い等を警告してくれる便利な機能があるが、新しい属性名に対応していないことがあり、正しい値なのにWarningが出てしまうことがある。

下記の例だと、「integrity」、「crossorigin」、「referrerpolicy」が未定義とWarningが出てしまっている。

Warningを非表示にする方法

  1. プロジェクトのプロパティから、検証のHTML構文を開く。
  2. 「プロジェクト固有の設定を可能にする」にチェックを入れる。
  3. 「指定された属性名を検証で無視」にチェックを入れる。
  4. 無視する属性名をカンマ区切りで入力する。

結果

下記の通りWarningは表示されなくなった。

Raspberry Pi 4のBiosは表示されるがOSが起動しない

Raspberry Pi 4のBiosは表示されるがOSが起動しない問題が発生した。

SSDの破損、モニタとの相性等確認したが問題なしで、確認を進めた結果、原因は電源供給のUSBアダプタにあった。

最近下記のUSBアダプタを購入したので、それをRaspberry Piの電源に使用したところ、今回の現象が発生した。Biosは表示されるがOSが起動する段階になるとRaspberry Piの電源が落ちてしまう。

下記の少し古いモデルに変更すると問題なくRaspberry OSが起動した。

USBケーブル等全て同じにして、USBアダプタのみの変更で問題が解決したので、おそらくUSBアダプタとの相性に問題があったのだと思う。

Local-Variable Type Inference ローカル変数宣言型推論

Java 10から、型の宣言を「var」で置き換えて省略することが出来るようになった。例えば、下記のように、

        var context = new ClassPathXmlApplicationContext(CONFIG_LOCATION);

        try (var stockFile = Files.newBufferedReader(Paths.get("src/stock1.txt");) {
        for (var i = 0; i < args.length; i++) {
        var executeFlag = true;

と記述することが出来る。積極的に使った方が良いか悩む。

桁あふれの心配をしなくて良いので、for分の初期化式の型宣言には便利かもしれない。

CircleCIとCOVERALLSを連携する

やりたいこと

CircleCIでテスト実行後、code coverageをCOVERALLSに表示したい。

COVERALLSの設定

レポジトリを登録して、SettingsのREPO TOKENをコピーする。

CircleCIの設定

先ほど確認したREPO TOKENをProject SettingのEnvironment VariablesにCOVERALLS_REPO_TOKENとして登録する。

config.ymlの設定

MavenのGoalにjacoco:report coveralls:reportを指定する。

      # Generate a site.
      - run:
          name: Site
          command: mvn jacoco:report coveralls:report
      - store_artifacts:
          path: target/site
          destination: reports

pom.xmlの設定

repoTokenにCOVERALLS_REPO_TOKENを設定する。

            <plugin>
                <groupId>org.eluder.coveralls</groupId>
                <artifactId>coveralls-maven-plugin</artifactId>
                <version>4.3.0</version>
                <configuration>
                    <repoToken>${COVERALLS_REPO_TOKEN}</repoToken>
                </configuration>
            </plugin>

動作確認

対象のGitHubレポジトリにpushすると、ビルドが動いた後、下記の通りcode coverageが表示されることが確認できた。

CircleCIのビルド後テスト結果が表示されるようにしたい

Junitのテスト結果を表示

Maven Testの後にJunitのテスト結果ファイルを収集する設定を追加する。

      # Publish test results.
      - run:
          name: Collect test results
          command: |
            mkdir -p ~/junit/
            find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} ~/junit/ \;
          when: always
      - store_test_results:
          path: ~/junit

下記の通りテスト結果が表示されるようになる。

Siteを表示

Mavenで実行したCheckStyle、SpotBugsやJavaDoc結果を表示するようにしたい。下記の通り設定ファイルに追記した。

      # Generate a site.
      - run:
          name: Site
          command: mvn site
      - store_artifacts:
          path: target/site
          destination: reports

ARTIFACTSタブからファイルが参照できるようになる。

完成した設定ファイルはGitHub参照のこと。
https://github.com/hide6644/common/blob/circleci-project-setup/.circleci/config.yml

GitHubにpushしたらCircleCIでビルドが実行されるようにしたい

やりたいこと

  • ビルドの実行
  • テストの実行
  • レポートの作成
  • バッジの表示

CircleCIの設定

CircleCIのプロジェクトをセットアップする

https://circleci.com/にアクセスし、GitHubアカウントでサインアップする。

自分の所有しているレポジトリが表示されるので、CircleCIと連携したいレポジトリのSet Up Projectをクリックする。

今回はconfigファイルの作成から行うのでFastを選択する。

ここは自身のプロジェクトで使用しているビルドツールを選択する。Java(Maven)を選択した。

Sampleのconfigファイルが作成される。とりあえず試したかったので、何も変更せずCommit and Runをクリックした。

該当のプロジェクトにcircleci-project-setupブランチが作成された後、ビルドが実行される。このsampleではビルドからテストまで実行される。

プログラムが使用しているデータベースの設定を行っていないため、当然テストは失敗となった。

プロジェクトに合わせてconfigファイルを変更する

自分の実行環境に合わせて以下の通りconfigファイルを変更した。

  • MariaDBをインストール
  • テスト用のスキーマ、データをインポート
# Use the latest 2.1 version of CircleCI pipeline process engine.
# See: https://circleci.com/docs/2.0/configuration-reference
version: 2.1

# Define a job to be invoked later in a workflow.
# See: https://circleci.com/docs/2.0/configuration-reference/#jobs
jobs:
  build-and-test:
    docker:
      - image: cimg/openjdk:11.0
      - image: cimg/mariadb:10.8
        environment:
          MARIADB_DATABASE: common
          MARIADB_USER: common
          MARIADB_PASSWORD: common_pw
    # Add steps to the job
    # See: https://circleci.com/docs/2.0/configuration-reference/#steps
    steps:
      # Checkout the code as the first step.
      - checkout
      # Use mvn clean and package as the standard maven build phase
      - run:
          name: Build
          command: mvn -B -DskipTests clean package
      # Wait for MariaDB to be ready.
      - run:
          name: Waiting DB setup
          command: |
            for i in `seq 1 10`;
            do
              nc -z 127.0.0.1 3306 && echo Success && exit 0
              echo -n .
              sleep 1
            done
            echo Failed waiting for MySQL && exit 1
      # Installation of MySQL CLI. And import test data.
      - run:
          name: Import tast data
          command: |
            sudo apt update
            sudo apt install mysql-client
            mysql -h 127.0.0.1 -u common -pcommon_pw common < src/config/schema.sql
            mysql -h 127.0.0.1 -u common -pcommon_pw common < src/config/data.sql
      # Then run tests!
      - run:
          name: Test
          command: mvn test

# Invoke jobs via workflows
# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
workflows:
  build-deploy:
    jobs:
      - build-and-test

これでビルドとテストは成功となった。

Junitのテスト結果、レポートの表示

こちら(CircleCIのビルド後テスト結果が表示されるようにしたい)の記事を参照のこと。

バッジの表示

Project SettingのStatus Badgesを参照する。埋め込み用コードが表示されるので、それをコピーして貼り付ける。

なぜか、URLの一部がnullになっていて、正常に画像が表示されなかったので、以下の通り修正した。

[![CircleCI](https://circleci.com/gh/hide6644/common/tree/circleci-project-setup.svg?style=svg)](https://circleci.com/gh/hide6644/common/tree/circleci-project-setup)