うごく生ゴミプログラマの備忘録

うごく生ゴミ 〜再臨〜

マビノギに楽天モバイルのテザリングで接続時にエラー(エラーコード20014)の対応

マビノギ楽天モバイルテザリングで接続時にエラー(エラーコード20014)が発生した。(マビノギ自体は起動するが、マビノギのID選択ダイアログが表示されず、エラーダイアログが表示される現象)

いろいろ調べたところ、とりあえず自分の環境では以下の手順で解決したので、同様の現象で困っている人&自分の備忘録のためにメモしときます。

コントールパネル ↓ ネットワークと共有設定 ↓ テザリングしているネットワークのプロパティから「インターネットプロトコル バージョン6(TCP/IPv6)」のチェックを外す ↓ OKボタンをクリック

で解決した。

↓はスクショ コントロールパネル

Docker Desktop(Mac版)がマルウェア扱いされた。アンインストールからHomebrew経由でインストールしたら解決した

なんか私物のPC(M1 Mac)のDocker Desktopがマルウェア扱いされる現象が現れて、 アンインストール ↓ 公式のインストーラーから再インストール ↓ 公式で公開されてるコマンドの実行

でも解決しなかったんだが、

アンインストール ↓ Homebrew経由でインストール

したら解決した。

コマンドは↓を実行した。

$ brew install --cask docker

外部ライブラリ使っているAWS Lambda関数(Python)のzipファイル作成シェルスクリプト(Poetry管理プロジェクト)

Poetryで管理しているPythonで書いたAWS Lambdaの関数(外部ライブラリも使っている)を、zipにまとめるスクリプトを書いたので備忘録として残しておく。

フォルダ構成

アプローチ

Poetryで管理している場合、 .venv/lib/python*/site-packages/ に poetry add したライブラリがインストールされるので、site-pckages 下のファイルと、自分で書いたソースコードをガッチャンコしたフォルダを作って、それをzipコマンドでzipにまとめるというやり方をした。

ただし .venv フォルダをプロジェクトディレクトリ内に作成するには、

poetry config virtualenvs.in-project true

で、Poetryの仮想環境をプロジェクトディレクトリ内に作成するよう設定が必要なので注意。

ワイはDockerfileに

RUN poetry config virtualenvs.in-project true

って書いてる。

スクリプト

build.sh の全文

#!/bin/sh

cd `dirname $0`
cd ../

rm -rf ./dist/
mkdir -p ./dist/package/

cp --recursive ./.venv/lib/python*/site-packages/. ./dist/package/
cp --recursive ./src/. ./dist/package/

cd ./dist/package/
zip -r ../package ./

cd ../
rm -rf ./package/

ポイント

srcディレクトリと.venv/lib/python*/site-packages/ を dist/package/ ディレクトリにコピーしている。

cp --recursive ./.venv/lib/python*/site-packages/. ./dist/package/
cp --recursive ./src/. ./dist/package/

zipを作成した後

zipを作成した後は、マネジメントコンソールからアップロードするなり、aws cli からアップロードするなり好きにしましょうという感じ。

ワイは以下のようなシェルスクリプト(deploy.shに該当)を書いて、S3にアップロードしてからLambda関数を更新するようにしてみた。

#!/bin/sh

cd `dirname $0`
cd ../

aws s3 cp ./dist/package.zip s3://<Amazon S3バケット名>/<S3キー>

aws lambda update-function-code \
    --function-name <AWS Lambda関数名> \
    --s3-bucket <バケット名> \
    --s3-key <S3キー>

LangChain(TypeScript)のRetrievalQAChainとOpenAI APIで、自前のドキュメントに関する質問に答えてくれるプログラムを作ってみた。

概要

OpenAIのChatGPTさん、めっちゃ頭良いけど、自分しか持って無くてインターネットに公開していない情報については回答してくれないので、自分しか持ってないドキュメントの内容に関する質問に回答してくれるプログラムを作ってみたので、その備忘録。

GitHubリポジトリ

こちらのリポジトリソースコードはアップロードしています。

github.com

使う技術

  • Node.js(バージョン18.14.2)

  • TypeScript

  • LangChain(TypeScript/JavaScript 版)

  • OpenAI APIAPIキーを発行します)

ダミーファイルを作成

そんなすぐに、良い感じのドキュメントを用意できないので、BingのAIさんに、いくつか社内用語を出力してもらって、それをテキストファイルとして保存しました。

テキストファイルはすべて documentsディレクトリに保存しています。

ディレクトリ構成

こんな感じ

create-vector フォルダ

documentsフォルダ内のテキストをvectorストアに保存するプログラム

call-query フォルダ

保存済のvectorストアを読み込み、質問の回答を得るプログラム

documents フォルダ

テキストファイルを保存しておくフォルダ(ここでは架空の企業の社内用語と説明のテキストファイル)

database フォルダ

ベクターストアの内容を保存しておくフォルダ

今回はベクターストアとして、ローカルに保存できるHNSWLibを利用します。

実行の流れ

ドキュメントの内容をベクターストアに保存するプログラムを実行する ↓ 保存済のvectorストアを読み込み、質問の回答を得るプログラムを実行する

プログラムのコード

create-vector-store/index.ts

documentsフォルダ内のドキュメントの内容をベクターストアに保存するプログラム

RecursiveCharacterTextSplitterで、ドキュメントの内容を100token以下になるまで分割しVectorStoreに保存しています。

import path from 'path';
import dotenv from 'dotenv';
import { OpenAIEmbeddings } from 'langchain/embeddings/openai';
import { DirectoryLoader } from 'langchain/document_loaders/fs/directory';
import { TextLoader } from "langchain/document_loaders/fs/text";
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
import { HNSWLib } from "langchain/vectorstores/hnswlib";


// .envファイルから環境変数を読み込み
dotenv.config();


const main = async function () {
  console.log("start");

  // 自前で準備したドキュメントを保存しているディレクトリの絶対パス
  const documentPath = path.join(__dirname, '../documents/');

  const directoryLoader = new DirectoryLoader(documentPath, {
    '.txt': (path) => {
      return new TextLoader(path)
    }
  });
  const documents = await directoryLoader.load();

  const splitter = new RecursiveCharacterTextSplitter({
    chunkSize: 100,
    chunkOverlap: 10,
  });

  const texts = await splitter.splitDocuments(documents);
  const embeddings = new OpenAIEmbeddings({
    openAIApiKey: process.env.OPENAI_API_KEY
  });
  const vectorStore = await HNSWLib.fromDocuments(texts, embeddings);

  const databasePath = path.join(__dirname, '../database/');
  await vectorStore.save(databasePath);

  console.log("end");
};

main();

call-query/index.ts

保存済のvectorストアを読み込み、質問の回答を得るプログラム

ここで、保存済のベクターストアから読み取り、RetrievalQAChainを使って自前のドキュメントの内容に対する質問に関する質問の回答を得ます。

import path from 'path';
import dotenv from 'dotenv';
import { OpenAIEmbeddings } from 'langchain/embeddings/openai';
import { OpenAI } from "langchain/llms/openai";
import { HNSWLib } from "langchain/vectorstores/hnswlib";
import { RetrievalQAChain } from "langchain/chains";


// .envファイルから環境変数を読み込み
dotenv.config();


const main = async function () {
  // 実行時引数が指定されているか確認
  if (process.argv.length < 3) {
    return;
  }

  const databasePath = path.join(__dirname, '../database/');
  const embeddings = new OpenAIEmbeddings();

  // 保存済のベクターストアから読み込み
  const vectorStore = await HNSWLib.load(databasePath, embeddings);

  const model = new OpenAI({
    openAIApiKey: process.env.OPENAI_API_KEY
  });
  const chain = RetrievalQAChain.fromLLM(model, vectorStore.asRetriever());

  // 実行時引数から質問内容を取得
  const query = process.argv[2];

  const { text } = await chain.call({ 
    query
  });

  // 質問内容と回答内容をコンソールに表示
  console.log(`Q: ${ query }\nA: ${ text }`);

};

main();

実行手順

ベクターストアの作成

$ cd <プロジェクトディレクトリ>/create-vector-store/
$ npm run start

質問をする

$ cd <プロジェクトディレクトリ>/create-vector-store/
$ npm run start --query=<質問>

実行結果例

ちゃんとdocumentsフォルダに保存しているドキュメントの内容に沿った回答をもらえました。

また、試しにdocumentsフォルダ内のドキュメントには記載の無い質問をすると、ちゃんと "分からない" 旨の回答がかえってきました。素直だな。

まとめ

とりあえず、自前で準備したドキュメントに関する回答を得ることができた。

今回はDirectoryLoaderの中で、テキストファイルに対してのみ読み取りを行っているが、これをPDFやWord、PowerPointに対応させれば、より汎用的に使えるようになるかもしれないなと思いました。

Dockerfileで、PATH通らなかった

最初こう書いてたんだけど、Node.jsのPATHが上手く通ってなくって、

ENV PATH $HOME/.nodebrew/current/bin:$PATH

↓のように書き直したら通りました。

ENV PATH /root/.nodebrew/current/bin:$PATH

github.com

以上でした。おやすみなさい。

技術書典2に出店しました

技術書典2に出店してきました。

techbookfest.org

参加された方とか運営の方とかおつかれさまでした。

今回は『TypeScriptでつくるシングルページアプリケーション』という本のみ販売しました。

TypeScriptでつくるシングルページアプリケーション内のソースは以下のリポジトリで公開しています。 また、今回印刷した30部しか刷らなかったため、すぐに売り切れてしまい、 「githubの方には本文は載ってないんですか?」って結構聞かれたので、リポジトリの方には、本文のソースとしてワードファイルをあげました。

Microsoft Office ワードを持っていない場合、Microsoft Office OnlineやLibre Officeなどで開けば、若干デザインは崩れるかもですが、一応読むことはできると思います。

また、同様の内容の本を4月30日の超技術書典でも販売する予定です。

techbookfest.org

次はポスター的なものとか、机の上にかけるシート的なものとか準備して、もう少しブースっぽく構えたいなーと思いました。

まる。