はじめに
RAG の実装を進めていると、コードを読むだけでは全体像を追いにくくなってきます。
ドキュメント解析、チャンク分割、インデックス作成、検索、回答生成、評価。個々の処理を理解していても、「どこから呼ばれて、どのデータを渡しているのか」を確認するには、複数のファイルを行き来する必要があります。
そこで今回は、Vercel Labs の OpenWiki をローカルで動かし、自分のプライベートな RAG リポジトリを Wiki 化しました。初回の完了した生成では、196 ファイルを索引し、ソース参照付きの Wiki を 26 ページ作成できました。その後、本文とナビゲーションを中国語にし、別途「中文分析报告」も追加しています。
この記事では、実際の配置、ソースの変更、環境変数、生成結果を整理します。
コード例のうち、パスの相対化、秘密情報の環境変数化、終了処理、ループバックへのバインドは、公開用に整理したものです。既存の実ファイルをそのまま転載したものではありません。今回の照合作業でサービスの再起動や Wiki の再生成は行っていません。
1. OpenWiki でできること
OpenWiki は、GitHub リポジトリをもとに、ソース参照付きのドキュメントサイトを作成する Next.js アプリケーションです。eve を利用して、大綱の作成、ページ生成、品質検査、公開までを進めます。
今回の目的は、RAG の実装をトピックごとに読める状態にすることでした。検索処理を調べたいときには関連する Wiki ページを開き、必要なところで参照元のソースコードに戻ります。
OpenWiki 自体の説明は、今回のベースと同じコミットの 公式 README を参照してください。以下は、この版にローカル変更を加えた構成です。
2. 今回の環境と、入力する GitHub URL
実際の配置は次のとおりです。
| 項目 | 照合した環境 |
|---|---|
| OS | Ubuntu 24.04.3 LTS(WSL 環境) |
| Node.js | v24.19.0 |
| OpenWiki | /u01/dsh_workspace/openwiki |
| PostgreSQL 起動スクリプト | /u01/dsh_workspace/.pg/start.mjs |
| PostgreSQL データ | /u01/dsh_workspace/.pg/data/db |
| 解析対象のローカル checkout | /u01/dsh_workspace/private_ai_poc |
| 解析する GitHub リポジトリ |
engchina/private_ai_poc(private、既定ブランチは main) |
| DB 接続先 |
127.0.0.1:5432、データベース名は postgres
|
| Wiki 成果物 | OpenWiki 配下の .openwiki/artifacts/
|
| LLM | 既存の OpenAI 互換エンドポイント |
OpenWiki の画面に入力するのは、次の URL です。
https://github.com/engchina/private_ai_poc
今回の URL 解析とソース取得の経路は GitHub 用です。/u01/dsh_workspace/private_ai_poc や file:///... を入力してローカルディレクトリを解析する機能ではありません。対象リポジトリのローカル checkout が同じマシンにあっても、この経路では GitHub から取得します。
したがって、ローカルで編集しただけの変更は反映されません。Wiki に反映したいコードは GitHub の対象ブランチへ反映する必要があります。
また、アプリと PostgreSQL をローカルで動かしても、GitHub と設定した LLM への通信は発生します。ソースの抜粋も LLM に渡されるため、「ローカル起動」は「完全オフライン」を意味しません。
3. ベースコミットと依存関係をそろえる
今回は次の版を使用しています。
| 項目 | 確認した値 |
|---|---|
| OpenWiki のベースコミット | 618dcaf862ede7f4e3103216f1de8e2956a84564 |
| Next.js | 16.2.9 |
| eve | 0.17.1 |
AI SDK の ai
|
7.0.0-beta.178 |
追加した @ai-sdk/openai-compatible
|
実インストール版 3.0.47
|
追加した postgres
|
実インストール版 3.4.9
|
別ディレクトリの embedded-postgres
|
実インストール版 18.4.0-beta.17
|
新しい作業ディレクトリで再現する場合は、Node.js 24 以上と pnpm を用意してから、次のようにベースを固定します。GitHub CLI は、後述する認証確認に使います。
git clone https://github.com/vercel-labs/openwiki.git
cd openwiki
git switch --detach 618dcaf862ede7f4e3103216f1de8e2956a84564
git switch -c local-private-wiki
pnpm install --frozen-lockfile
pnpm add --save-exact postgres@3.4.9 @ai-sdk/openai-compatible@3.0.47
以降のソース変更は、このベース向けです。既に動いている環境では取得し直さず、まず現在の状態を確認します。
git rev-parse HEAD
git status --short
git diff --stat
実環境には未コミットのローカル変更があります。git rev-parse HEAD の値だけでは、その変更内容までは再現できません。移設時は、秘密情報を除いたソース差分と、対応する package.json、pnpm-lock.yaml も管理します。
なお、後述する 3cbe232... は解析対象の RAG リポジトリのコミットであり、OpenWiki のコミットではありません。
4. プライベートリポジトリを読み込めるようにする
GitHub 認証を確認する
まず、対象リポジトリへのアクセスを確認します。
gh auth status
gh api repos/engchina/private_ai_poc --jq '{full_name, private, default_branch}'
照合時は full_name: engchina/private_ai_poc、private: true、default_branch: main でした。
OpenWiki を起動するシェルにトークンを渡す場合は、次のようにします。
export GITHUB_TOKEN="$(gh auth token)"
実環境では .env.local にも GITHUB_TOKEN が設定されています。プロセス環境とファイルの両方を使う場合は、意図したトークンが有効になるように管理します。この値をブラウザー向けの NEXT_PUBLIC_ 変数には入れません。
OpenWiki 側の private 拒否処理を変更する
ベース版には、GitHub の認証とは別に private リポジトリを拒否する処理があります。公式 README も公開デプロイで private を拒否する方針を説明しています。したがって、トークンの設定だけでは十分ではありません。公式の Deploy 説明
実環境では次の 3 か所を変更しています。
| ファイル | 対象 | 変更内容 |
|---|---|---|
lib/github-repository.ts |
assertPublicGitHubRepository() |
private を理由に例外を投げる処理を外す |
lib/github-repository.ts |
githubRepositoryExists() |
private を理由に false を返す処理を外す |
agent/lib/github-repo.ts |
assertPublicGitHubRepository() |
agent 側の同じ拒否処理を外す |
両ファイルの assertPublicGitHubRepository() は、現在次の形です。関数名には元の Public が残っています。
function assertPublicGitHubRepository(metadata: { private?: unknown }) {
// ローカル環境では、GITHUB_TOKEN で取得できるリポジトリを許可する。
void metadata;
}
githubRepositoryExists() では、HTTP ステータスの検査を残したまま、成功レスポンスの末尾を次のようにしています。
- const metadata = (await response.json()) as { private?: unknown };
- if (metadata.private === true) {
- return false;
- }
+ void (await response.json());
return true;
GitHub API のエラー処理や Authorization ヘッダーの付与は残します。検索候補を返す app/api/repositories/search/route.ts には private を除外する処理が残っているため、今回の操作は URL の直接入力を前提にしています。
この変更は Wiki 閲覧者の認証を追加しません。サーバーのトークンで取得した非公開コードが Wiki に含まれるため、本記事の再現例はループバックで待ち受ける個人用構成です。
5. embedded-postgres で PostgreSQL を起動する
実環境では、OS に PostgreSQL サービスを新規導入する方法ではなく、embedded-postgres から PostgreSQL プロセスを起動しています。データベース名は、初期化時に作成される postgres です。旧稿にあった openwiki データベースを追加作成する手順は、実際の配置とは異なっていました。
以下は、新しい環境向けに整理した起動例です。実環境の .pg に相当するディレクトリを、OpenWiki と同じ親ディレクトリに用意します。
mkdir -p ../.pg
cd ../.pg
npm init -y
npm install --save-exact embedded-postgres@18.4.0-beta.17
このパッケージは PostgreSQL バイナリの利用にインストールスクリプトを必要とします。スクリプトを無効にしている場合は、パッケージの案内に従って必要な処理を許可します。embedded-postgres の説明
start.mjs を次の内容で作成します。
import EmbeddedPostgres from 'embedded-postgres';
import { existsSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { join } from 'node:path';
const password = process.env.OPENWIKI_PG_PASSWORD;
if (!password) {
throw new Error('OPENWIKI_PG_PASSWORD を設定してください');
}
// 起動するシェルのカレントディレクトリに依存しない配置にする。
const databaseDir = fileURLToPath(new URL('./data/db', import.meta.url));
const pg = new EmbeddedPostgres({
databaseDir,
user: 'postgres',
password,
port: 5432,
persistent: true,
postgresFlags: ['-h', '127.0.0.1'],
});
let started = false;
let stopping = false;
async function stop() {
if (stopping) return;
stopping = true;
try {
if (started) await pg.stop();
} finally {
process.exit(0);
}
}
if (!existsSync(join(databaseDir, 'PG_VERSION'))) {
await pg.initialise();
}
await pg.start();
started = true;
process.on('SIGINT', stop);
process.on('SIGTERM', stop);
const client = pg.getPgClient('postgres', '127.0.0.1');
try {
await client.connect();
const result = await client.query('SELECT current_database() AS database');
console.log('PostgreSQL ready:', result.rows[0].database);
} catch (error) {
await pg.stop();
throw error;
} finally {
await client.end();
}
一般ユーザーで起動し、このターミナルは開いたままにします。
read -rsp 'PostgreSQL password: ' OPENWIKI_PG_PASSWORD
export OPENWIKI_PG_PASSWORD
node start.mjs
これは初期化と接続確認を含む公開用の例です。実際の短い起動スクリプトには上記の終了処理や明示的な -h 指定はありませんが、照合時の PostgreSQL は 127.0.0.1:5432 で待ち受けていました。
既存クラスタが動いている場合は、同じデータディレクトリで二重起動しません。また、初期化後に OPENWIKI_PG_PASSWORD を変えても DB 内のパスワードは変わりません。既存クラスタでは、既存のパスワードと一致させて接続します。
OpenWiki の .env.local に指定する URL は、次の形です。
DATABASE_URL=postgres://postgres:YOUR_URL_ENCODED_PASSWORD@127.0.0.1:5432/postgres
OPENWIKI_LOCAL_ARTIFACTS=1
パスワードに URL の予約文字が含まれる場合は、パスワード部分を URL エンコードします。OpenWiki のテーブルは lib/storage.ts の ensureSchema() によって初回の DB 利用時に作成されます。PostgreSQL プロセスと、接続先データベースは先に存在している必要があります。
ローカル成果物を使う条件
この版の shouldUseLocalArtifacts() は、次の条件をすべて満たした場合にローカル保存を選びます。
-
VERCELが1ではない。 -
OPENWIKI_LOCAL_ARTIFACTS=1が設定されている。 - 利用可能な Blob 書き込み認証情報がない。
そのため、Vercel から取得した Blob の設定が残っていると、OPENWIKI_LOCAL_ARTIFACTS=1 だけではローカル保存に切り替わらない場合があります。今回の .env.local に Blob 用設定はありません。ローカル保存には、このマシン専用の DB を組み合わせます。実装の Storage 判定
6. Neon の HTTP クエリから PostgreSQL の TCP 接続へ変更する
ベース版の lib/storage.ts は、@neondatabase/serverless の neon() を使います。この関数のクエリ経路は HTTP です。旧稿にあった「このストレージ層が WebSocket 経路を使っていた」という説明は不正確でした。Neon ドライバーの Pool / Client が WebSocket を使う経路と区別します。Neon ドライバーの公式説明
通常の PostgreSQL を 127.0.0.1:5432 で起動しても、Neon 用 HTTP サービスがそのポートに生えるわけではありません。そこで、今回のローカル配置では Postgres.js の postgres を使って TCP 接続します。
実際のストレージ変更は、次の 3 点です。
- import { neon } from "@neondatabase/serverless";
+ import postgres from "postgres";
- type Sql = ReturnType<typeof neon>;
+ type Sql = ReturnType<typeof postgres>;
async function getSql(): Promise<Sql> {
- sqlClient ??= neon(getDatabaseUrl());
+ sqlClient ??= postgres(getDatabaseUrl());
schemaReady ??= ensureSchema(sqlClient);
await schemaReady;
return sqlClient;
}
既存の sqlClient の再利用、schemaReady、タグ付きテンプレートによる SQL と asRows() は維持しています。この版の利用方法に合わせた変更であり、Neon の別の API を使う任意のアプリにそのまま適用できるという意味ではありません。Postgres.js の接続方法
7. OpenAI 互換エンドポイントにモデル呼び出しを接続する
実環境では、agent/lib/model-config.ts を変更して OpenAI 互換 provider のモデルオブジェクトを返しています。Gateway 用のモデル ID 文字列を返す元の経路から切り替えるため、モデル名の変更だけでは完了しません。
接続先は運用上 vLLM と呼んでいるエンドポイントです。ただし、今回照合できたのはクライアントの設定と実装であり、推論サーバー内部のソフトウェアや重みではありません。モデル識別子 claude-opus-5 も、この環境が使用する ID として扱います。
実際の変数名に合わせる
実環境のモデル設定コードが読む変数は、次の 4 つです。
| 変数 | 用途 |
|---|---|
OPENWIKI_BASE_URL |
OpenAI 互換 API のベース URL。今回のローカル変更で追加 |
OPENWIKI_API_KEY |
同 API のキー。今回のローカル変更で追加 |
OPENWIKI_AGENT_MODEL |
通常の agent が使用するモデル ID |
OPENWIKI_INDEX_MODEL |
大綱とページ生成が使用するモデル ID |
旧稿の LOCAL_LLM_* は説明用に作った別名であり、実配置のコードは読みません。ここでは実際の変数名に統一します。
実配置はソース内の既定値でも動く形ですが、公開用のコードでは接続先と API キーをハードコードせず、明示的な設定を要求します。agent/lib/model-config.ts 全体の例は次のとおりです。
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import type { LanguageModel } from "ai";
function requiredEnv(key: string): string {
const value = process.env[key]?.trim();
if (!value) throw new Error(`${key} is required`);
return value;
}
const vllm = createOpenAICompatible({
name: "vllm",
baseURL: requiredEnv("OPENWIKI_BASE_URL"),
apiKey: requiredEnv("OPENWIKI_API_KEY"),
supportsStructuredOutputs: true,
});
export function getOpenWikiAgentModel(): LanguageModel {
return vllm.chatModel(requiredEnv("OPENWIKI_AGENT_MODEL"));
}
export function getOpenWikiIndexModel(): LanguageModel {
return vllm.chatModel(requiredEnv("OPENWIKI_INDEX_MODEL"));
}
対応する設定例です。
OPENWIKI_BASE_URL=http://YOUR_LLM_HOST:PORT/v1
OPENWIKI_API_KEY=YOUR_API_KEY
OPENWIKI_AGENT_MODEL=YOUR_SERVED_MODEL_ID
OPENWIKI_INDEX_MODEL=YOUR_SERVED_MODEL_ID
モデル ID には接続先が受け付ける名前を指定します。AI Gateway の名前を、そのまま別の provider に渡せるとは限りません。provider の作成方法は AI SDK の OpenAI Compatible Providers に説明されています。
直接生成する経路の型も変更する
agent/lib/indexing/run-index-job.ts には、直接 generateText() を呼ぶ経路もあります。モデル設定の戻り値に合わせて、次の型変更も必要です。
- import { generateText, Output } from "ai";
+ import { generateText, Output, type LanguageModel } from "ai";
- function getIndexModel(): string {
+ function getIndexModel(): LanguageModel {
return getOpenWikiIndexModel();
}
これにより、通常の agent、大綱用 agent、ページ用 agent、直接生成するコードが、共通のモデル設定を利用できます。
構造化出力とコンテキスト長
今回の設定には supportsStructuredOutputs: true が入っています。これは SDK が構造化出力を要求するとき、接続先の json_schema 対応を利用するための設定です。非対応のサーバーに機能を追加する設定ではなく、通常のテキスト応答が成功することだけでも対応確認にはなりません。
履歴には構造化されたページ結果を得られず失敗した実行があります。ただし、保存された履歴だけから、すべての失敗をこの設定一つの有無に帰することはできません。schema 対応、出力の打ち切り、生成時間、品質検査を合わせて確認します。
また、次の 3 ファイルの defineAgent() には modelContextWindowTokens: 262144 を追加しています。
agent/agent.tsagent/subagents/outline_generator/agent.tsagent/subagents/page_generator/agent.ts
それぞれ既存の model、description などを残し、設定オブジェクトへ次のフィールドを加えます。
modelContextWindowTokens: 262144,
これは eve 側に伝えるコンテキスト長です。モデルや推論サーバーの実際の上限を拡大するものではありません。別の接続先では、そのサーバーとモデルが実際に受け付ける値に合わせます。
8. ページ並列数とタイムアウトは環境変数で調整する
今回のベース版には、並列数とタイムアウトを上書きする環境変数が既に実装されています。この調整のために既定の定数をソースで書き換えたわけではありません。
実環境の .env.local は次の値です。
OPENWIKI_PAGE_WORKER_CONCURRENCY=3
OPENWIKI_OUTLINE_WORKER_TIMEOUT_MS=600000
OPENWIKI_PAGE_WORKER_TIMEOUT_MS=600000
OPENWIKI_ACTIVE_JOB_STALE_MS=7200000
| 項目 | この版の既定値 | 実環境の設定 |
|---|---|---|
| ページ生成の並列数 | 16 |
3 |
| 大綱 worker のタイムアウト |
360000 ms(6 分) |
600000 ms(10 分) |
| ページ worker のタイムアウト |
180000 ms(3 分) |
600000 ms(10 分) |
| 実行中ジョブの無進捗判定 |
900000 ms(15 分) |
7200000 ms(2 時間) |
大綱とページの既定タイムアウトは同じではありません。また、OPENWIKI_ACTIVE_JOB_STALE_MS はジョブの updatedAt からの経過時間に対する閾値です。ジョブ全体の実行時間を 2 時間に制限する設定ではありません。
eve セッション開始前のタイムアウトには、別の OPENWIKI_PRE_SESSION_STALE_MS があります。この環境では上書きされておらず、ベース版の既定値は 20 分です。
実際に初回完了へ至るまでに、無進捗判定やページ品質検査で失敗したジョブが記録されています。共有エンドポイントの負荷を抑える目的で並列数を下げましたが、今回の照合では推論サーバーの待ち行列自体は計測していません。タイムアウトの原因をすべて待ち行列と断定せず、OpenWiki と推論側の記録を合わせて判断します。
実環境では、繰り返し検証するため、生成要求のレート制限も無効になっています。
OPENWIKI_GENERATION_RATE_LIMIT_ENABLED=0
これは生成要求の受付制限であり、ページ worker の同時実行数とは別です。共有する環境では必要な制限を設定します。
9. 中国語 Wiki に合わせた追加変更
現在の環境は、本文とナビゲーションを簡体字中国語で表示しています。そのためのソース変更が、旧稿には抜けていました。
大綱と本文の両方に言語を指定する
agent/lib/indexing/prompt.ts の createOutlinePrompt() と createPageGenerationPrompt() に、言語に関する指示を追加しています。
大綱では title、summary、概念の説明、ナビゲーションのタイトル、ページの purpose を簡体字中国語にします。ページ生成では見出しと本文を中国語にし、次の項目は翻訳しません。
- slug:小文字 ASCII の kebab-case を維持する。
- ファイルパス、コード識別子、コマンド、設定キー:元の表記を維持する。
- 品質検査に使う
## Relevant Source FilesとSources::英語のまま維持する。
既存の英語ページに対応するトピックについては、overview、installation、architecture などの slug を再利用する指示も加えています。これは既存 URL を維持するための、このリポジトリ向けの調整です。他のリポジトリへ適用するときは、このプロジェクト専用の slug 一覧をそのまま使わないようにします。
英単語だけを数える品質検査を調整する
元の countWords() は主に英数字の単語を数えるため、中国語本文が十分長くても語数不足と判定される可能性があります。
agent/lib/indexing/run-index-job.ts では、コードや参照行などを除外する処理を維持し、漢字の文字数を追加しています。実配置の処理は次の形です。
function countWords(markdown: string): number {
const text = markdown
.replace(/```[\s\S]*?```/g, " ")
.replace(/`[^`\n]+`/g, " ")
.replace(/^.*\bSources:\s*.*$/gim, " ")
.replace(/https?:\/\/\S+/g, " ")
.replace(/[A-Za-z0-9_.-]+\/[A-Za-z0-9_./-]+/g, " ");
const latinWords = text.match(/[A-Za-z0-9][A-Za-z0-9'-]*/g)?.length ?? 0;
const cjkChars = text.match(/[\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]/g)?.length ?? 0;
return latinWords + cjkChars;
}
これは「漢字 1 文字を 1 単位として加算する」という、この環境の品質検査用の近似です。中国語の単語分割や、全 CJK 文字、かな、ハングルを網羅する実装ではありません。
なお、これらの変更が入っていることと、現在表示している中国語版の全ページが通常のジョブで一度に生成・公開されたことは別です。現在の DB では、中国語の 26 ページは generated_by_job_id が空で、後続の生成ジョブには失敗記録が残っています。本記事では、現在の中国語表示を「通常の中国語再生成ジョブの完了実績」としては数えません。
10. 設定をまとめて、起動する
公開用に整理したモデル設定コードを使う場合、OpenWiki の .env.local は次の形になります。値は自分の接続先に置き換えます。
DATABASE_URL=postgres://postgres:YOUR_URL_ENCODED_PASSWORD@127.0.0.1:5432/postgres
OPENWIKI_LOCAL_ARTIFACTS=1
# 起動シェルで GITHUB_TOKEN を export する場合、この行は不要。
GITHUB_TOKEN=YOUR_GITHUB_TOKEN
OPENWIKI_BASE_URL=http://YOUR_LLM_HOST:PORT/v1
OPENWIKI_API_KEY=YOUR_API_KEY
OPENWIKI_AGENT_MODEL=YOUR_SERVED_MODEL_ID
OPENWIKI_INDEX_MODEL=YOUR_SERVED_MODEL_ID
OPENWIKI_PAGE_WORKER_CONCURRENCY=3
OPENWIKI_OUTLINE_WORKER_TIMEOUT_MS=600000
OPENWIKI_PAGE_WORKER_TIMEOUT_MS=600000
OPENWIKI_ACTIVE_JOB_STALE_MS=7200000
# 個人のローカル検証で、生成要求の受付制限を無効にする場合のみ。
OPENWIKI_GENERATION_RATE_LIMIT_ENABLED=0
実環境の .env.local には OPENWIKI_TELEMETRY_DISABLED=1 もありますが、OpenWiki 本体の確認したソースにはこの変数を読む処理が見つかりません。この設定だけで計測や外部通信が停止すると説明することはできないため、再現に必要な設定例には含めていません。
PostgreSQL を起動した状態で、OpenWiki のディレクトリから確認と起動を行います。
pnpm typecheck
pnpm build
pnpm dev --hostname 127.0.0.1
ここでの型チェックとビルドは、変更を適用した環境で実施する手順です。この記事の照合作業で新たにビルド成功を確認した、という意味ではありません。
ブラウザーで OpenWiki のトップページ を開き、https://github.com/engchina/private_ai_poc を入力します。既に Wiki がある今回の環境では、private_ai_poc の Wiki に直接アクセスできます。
実配置の起動ログには next dev --turbopack とあり、照合時の 3000 ポートはループバック限定ではありませんでした。上の --hostname 127.0.0.1 は公開用の再現手順で追加した指定です。
別の PC からサーバー上の Wiki を見る場合は、例えば SSH トンネルを使います。
ssh -N -L 3000:127.0.0.1:3000 user@YOUR_SERVER
接続中に手元のブラウザーで http://127.0.0.1:3000 を開きます。手元の 3000 ポートを別のアプリが使っている場合は、転送元を別の空きポートに変更します。
11. 初回生成と現在の表示を分けて確認する
初回の完了した生成
DB に残る完了ジョブは、日本時間 2026 年 9 月 11 日の 12:13:44 頃に開始し、12:28:52 頃に完了しています。
| 項目 | 確認結果 |
|---|---|
| 対象のソースコミット | 3cbe232b4418874c848d2964e001b64164673b04 |
| ブランチ | main |
| 初回 revision のソースファイル数 | 196 |
| 初回の Wiki |
26 ページ |
| 生成完了の状態 | ジョブの status と phase は completed
|
196 は、この revision の source_files と保存済み file-inventory.json で確認した索引ファイル数です。リポジトリ内のすべてのファイル数や、各ファイルをモデルが全文読んだ回数を示すものではありません。
現在の公開状態
照合時の GET /api/repositories/engchina/private_ai_poc は成功し、次の状態を返しました。
| 項目 | 現在の状態 |
|---|---|
| リポジトリ名 | engchina/private_ai_poc |
| 参照するソースコミット | 初回と同じ 3cbe232b4418874c848d2964e001b64164673b04
|
| 現在の repository revision | 6d49b346-65b9-498e-a2f5-8375ab4a3a82 |
その revision の indexedAt
|
2026 年 9 月 11 日 15:22:51 頃(日本時間) |
API の pages 件数 |
27 |
| 通常の Wiki ページ | 中国語タイトル・本文の 26 ページ。構造化引用あり |
| 追加ページ |
chinese-analysis(中文分析报告)。構造化引用 artifact なし |
| 実行中ジョブの参照 |
active_index_job_id は null
|
現在の 26 ページの本文 revision は後から更新されています。一方、追加の chinese-analysis は初回の repository revision にひも付きます。そのため、「現在 27 ページある」「初回ジョブで 26 ページを生成した」「その後に中国語版へ更新した」を区別して記録します。
Overview は中国語の「概览」として取得でき、構造化引用は 6 件でした。アーキテクチャ、データ契約、解析、チャンク分割、インデックスとストレージ、回答生成、ナレッジ管理、Oracle ADB・OCI アダプター、評価、Viewer、検証 UI、CI などをトピック単位で参照できます。
ソース参照があっても、生成文章の正しさが保証されるわけではありません。特に、実行時の設定で変わる処理やデータの受け渡しは、対応するコミットのソースと照合して読みます。
成果物のディレクトリ構造
実際の成果物は次の構造です。
.openwiki/artifacts/
└── repos/<repository-id>/
├── revisions/<commit-sha>/
│ ├── file-inventory.json
│ └── source-index.json
└── wiki/<page-id>/revisions/
├── <page-revision-id>.md
└── <page-revision-id>.citations.json
上は基本形です。現在の中国語本文には、過去に作成した引用 artifact を参照するものがあります。常に同じ basename の .md と .citations.json が対になっている、と仮定せず、DB の content_artifact_id と citations_artifact_id の対応を確認します。
rg --files --hidden --no-ignore .openwiki/artifacts \
-g '*.md' -g '*.citations.json' -g 'file-inventory.json' -g 'source-index.json'
--hidden だけでは Git の ignore 規則が残るため、生成物を確認するコマンドには --no-ignore も付けています。
ディスクには過去の本文 revision や現在の表示に使っていないページも残っています。今回のディスクには Markdown が 54 ファイル、ページ ID のディレクトリが 28 個ありましたが、API のページ一覧は 27 件です。公開ページ数を単純なファイル数で数えないようにします。
また、本文ファイルだけをコピーしても、DB のナビゲーション、repository revision、ページ revision、引用の対応は移りません。移設では DB と成果物を整合する状態で扱います。
12. コード更新後に再生成する
GitHub 側の対象ブランチへコードを反映した後、次の API で再生成を要求できます。URL は現在の名前を使います。
curl --fail-with-body -X POST \
'http://127.0.0.1:3000/api/repositories' \
-H 'Content-Type: application/json' \
--data '{"repoUrl":"https://github.com/engchina/private_ai_poc","force":true}'
この版の POST /api/repositories は repoUrl と force を受け付けます。force: true は、公開済み revision があっても索引開始の経路へ進める指定です。
ただし、正常な実行中ジョブが既にある場合は、そのジョブを返して再利用します。force は、動いているジョブを強制終了したり、必ず別のジョブを並列起動したりする指定ではありません。
レスポンスが 202 でも生成完了ではありません。返された job.id を使い、進捗を確認します。
curl --fail-with-body \
'http://127.0.0.1:3000/api/index-jobs/YOUR_JOB_ID'
この進捗 API は、無進捗の実行中ジョブを検出すると失敗扱いへ更新する処理も含みます。OPENWIKI_ACTIVE_JOB_STALE_MS が進捗確認時の判定にも使われる点に注意します。
完了後に Wiki API を確認します。
curl --fail-with-body \
'http://127.0.0.1:3000/api/repositories/engchina/private_ai_poc'
確認するのは、ジョブが completed になったこと、意図した commitSha が表示されること、本文・ナビゲーション・引用が読めることです。現在の中国語版や追加レポートには通常ジョブと異なる更新履歴があるため、再生成後もそれらが期待どおり残っているか確認します。
13. つまずいた点と修正の整理
| 症状・旧稿の記述 | 実装・実環境に合わせた整理 |
|---|---|
private_ai_poc を入力する |
現在は engchina/private_ai_poc。旧名は照合時に 404 |
| トークンがあれば private を取得できる | GitHub 権限に加え、OpenWiki の 3 か所の拒否処理を変更 |
| Neon の WebSocket 接続で失敗する | 対象コードは neon() の HTTP クエリ。postgres による TCP 接続へ変更 |
DB 名は openwiki
|
実環境は postgres
|
LOCAL_LLM_* を設定する |
実コードは OPENWIKI_BASE_URL、OPENWIKI_API_KEY、既存のモデル変数を読む |
| モデル設定ファイルを変更すれば完了 | 直接生成経路の戻り値の型と、3 agent のコンテキスト長も確認 |
| 大綱とページのタイムアウトは両方 3 分 | 既定は大綱 6 分、ページ 3 分。両方を環境変数で 10 分に設定 |
| 並列数とタイムアウトをソースで変更 | この版には既存の環境変数があり、実配置はその上書きを利用 |
| 中国語はモデルへの指示だけで対応 | 大綱・本文の指示、slug と検査マーカーの維持、漢字を含む長さ検査を追加 |
| 現在の Wiki は 26 ページ | 初回生成は 26。現在の API は 26 ページ+追加レポート 1 ページ |
| 現在の中国語表示は通常の再生成完了を証明する | DB 上のページ更新と生成ジョブの完了記録を区別する |
force: true なら必ず新しいジョブを作る |
正常な実行中ジョブがある場合は再利用する |
リポジトリへのアクセス、DB の接続方式、LLM の provider、品質検査を環境に合わせたことで、RAG の実装をトピックごとに読み、必要な箇所からソースへ戻れるようになりました。今後の更新でも、生成結果の見た目だけでなく、対象コミット、ジョブの完了状態、引用との対応を一緒に確認していきます。
参考資料
- 元の記事
- 今回の OpenWiki ベースコミット
- OpenWiki の固定版 README
- 固定版のモデル設定
- 固定版の生成処理と worker 設定
- 固定版の無進捗判定
- Neon serverless ドライバー
- Postgres.js
- embedded-postgres
- AI SDK の OpenAI Compatible Providers
実環境の値と公開状態は上記の公式資料だけから推定せず、配置済みソースと設定、ローカル DB の読み取り専用トランザクション、既存 Wiki の API 応答、認証付き GitHub API の結果から確認しています。非公開リポジトリの本文、実 API キー、トークン、DB パスワードは記事へ転載していません。