@orizm/cli 3.2.0 → 3.3.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-Bd30EhQC.mjs → agent-Kf8iuW2I.mjs} +2 -2
- package/dist/{agent-Bd30EhQC.mjs.map → agent-Kf8iuW2I.mjs.map} +1 -1
- package/dist/{agent-vC2-9rjt.cjs → agent-UZZtdOZS.cjs} +2 -2
- package/dist/{agent-vC2-9rjt.cjs.map → agent-UZZtdOZS.cjs.map} +1 -1
- package/dist/cli/main.cjs +4 -4
- package/dist/cli/main.mjs +4 -4
- package/dist/{cms-DLOypcw8.mjs → cms-8XZhxwsM.mjs} +5 -2
- package/dist/{cms-DLOypcw8.mjs.map → cms-8XZhxwsM.mjs.map} +1 -1
- package/dist/{cms-CId7jg5l.cjs → cms-C4zEtppZ.cjs} +5 -2
- package/dist/{cms-CId7jg5l.cjs.map → cms-C4zEtppZ.cjs.map} +1 -1
- package/dist/{codegen-kbbIwPbb.cjs → codegen-Cypg4O3L.cjs} +3 -3
- package/dist/{codegen-kbbIwPbb.cjs.map → codegen-Cypg4O3L.cjs.map} +1 -1
- package/dist/{codegen-BKE_IYoM.mjs → codegen-Dnjv7zfm.mjs} +3 -3
- package/dist/{codegen-BKE_IYoM.mjs.map → codegen-Dnjv7zfm.mjs.map} +1 -1
- package/dist/config/index.cjs +4 -2
- package/dist/config/index.cjs.map +1 -1
- package/dist/config/index.d.mts +8 -1
- package/dist/config/index.d.mts.map +1 -1
- package/dist/config/index.mjs +4 -2
- package/dist/config/index.mjs.map +1 -1
- package/dist/{config-loader-D8x32gEU.cjs → config-loader-CZfANHBf.cjs} +2 -2
- package/dist/config-loader-CZfANHBf.cjs.map +1 -0
- package/dist/{config-loader-BEgS869e.mjs → config-loader-CtbZOGjc.mjs} +3 -3
- package/dist/config-loader-CtbZOGjc.mjs.map +1 -0
- package/dist/{consumer-OG6IEJun.cjs → consumer-BSgriLn0.cjs} +2 -2
- package/dist/{consumer-OG6IEJun.cjs.map → consumer-BSgriLn0.cjs.map} +1 -1
- package/dist/{consumer-CqyZdG9v.mjs → consumer-s8LnLw4e.mjs} +2 -2
- package/dist/{consumer-CqyZdG9v.mjs.map → consumer-s8LnLw4e.mjs.map} +1 -1
- package/dist/docs/features/cli/commands/schema.md +3 -2
- package/dist/docs/features/cms-sdk/install.md +1 -1
- package/dist/docs/features/console/audit-logs.md +3 -0
- package/dist/docs/features/consumer-sdk/install.md +1 -1
- package/dist/docs/features/dictionary.md +268 -0
- package/dist/docs/features/full-text-search/local-development.md +145 -0
- package/dist/docs/features/full-text-search.md +146 -0
- package/dist/docs/features/schema/database.md +9 -8
- package/dist/docs/index.md +3 -1
- package/dist/docs/manifest.json +3 -3
- package/dist/{erd-BNv5Th6z.mjs → erd-BihhEfZ_.mjs} +2 -2
- package/dist/{erd-BNv5Th6z.mjs.map → erd-BihhEfZ_.mjs.map} +1 -1
- package/dist/{erd-ByuVMQ5n.cjs → erd-DmnB1v2c.cjs} +2 -2
- package/dist/{erd-ByuVMQ5n.cjs.map → erd-DmnB1v2c.cjs.map} +1 -1
- package/dist/{init-CPfpVlUN.mjs → init-BpKpTQ0z.mjs} +66 -13
- package/dist/init-BpKpTQ0z.mjs.map +1 -0
- package/dist/{init-NaL2N3Go.cjs → init-BrZCChEG.cjs} +66 -13
- package/dist/init-BrZCChEG.cjs.map +1 -0
- package/dist/{push-9fPpd4U8.cjs → push-BggkrD0g.cjs} +28 -10
- package/dist/push-BggkrD0g.cjs.map +1 -0
- package/dist/{push-54rmb0T0.mjs → push-xWnD9oov.mjs} +28 -10
- package/dist/push-xWnD9oov.mjs.map +1 -0
- package/dist/{run-codegen-mclysZuT.cjs → run-codegen-B-90rvjk.cjs} +2 -2
- package/dist/run-codegen-B-90rvjk.cjs.map +1 -0
- package/dist/{run-codegen-DjnV60bE.mjs → run-codegen-CrO08jJT.mjs} +2 -2
- package/dist/run-codegen-CrO08jJT.mjs.map +1 -0
- package/dist/{schema-CNSTXsVa.cjs → schema-CUVTXrHk.cjs} +4 -4
- package/dist/{schema-CNSTXsVa.cjs.map → schema-CUVTXrHk.cjs.map} +1 -1
- package/dist/{schema-BL6SlLtH.mjs → schema-DlUWHV_t.mjs} +4 -4
- package/dist/{schema-BL6SlLtH.mjs.map → schema-DlUWHV_t.mjs.map} +1 -1
- package/dist/{validate-BpxZ8LTl.cjs → validate-BH8jqdqq.cjs} +2 -2
- package/dist/{validate-BpxZ8LTl.cjs.map → validate-BH8jqdqq.cjs.map} +1 -1
- package/dist/{validate-Ca0CRo16.mjs → validate-COS4bfr0.mjs} +2 -2
- package/dist/{validate-Ca0CRo16.mjs.map → validate-COS4bfr0.mjs.map} +1 -1
- package/package.json +8 -8
- package/dist/config-loader-BEgS869e.mjs.map +0 -1
- package/dist/config-loader-D8x32gEU.cjs.map +0 -1
- package/dist/init-CPfpVlUN.mjs.map +0 -1
- package/dist/init-NaL2N3Go.cjs.map +0 -1
- package/dist/push-54rmb0T0.mjs.map +0 -1
- package/dist/push-9fPpd4U8.cjs.map +0 -1
- package/dist/run-codegen-DjnV60bE.mjs.map +0 -1
- package/dist/run-codegen-mclysZuT.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consumer-
|
|
1
|
+
{"version":3,"file":"consumer-s8LnLw4e.mjs","names":[],"sources":["../src/cli/codegen/consumer.ts","../src/cli/commands/codegen/consumer.ts"],"sourcesContent":["import { CommonOrizmConfig } from \"../types.js\";\nimport { formatTsWithPrettier } from \"./format.js\";\nimport {\n AUTOGEN_HEADER,\n UTILITIES,\n RenderColumn,\n RenderIndex,\n toCodeTypeName,\n renderColumnField,\n renderTypeBlock,\n renderRefsFieldLines,\n renderUniqueFieldLines,\n renderModuleRowTypeBlock,\n renderModuleDescriptorBlock,\n renderSection,\n renderWebhookTypesSection,\n} from \"./render.js\";\n\ntype RenderTable = {\n name: string;\n columns: RenderColumn[];\n enableForm?: boolean;\n enableDrafts?: boolean;\n indexes?: RenderIndex[];\n};\n\nexport function renderConsumerModule(\n config: CommonOrizmConfig,\n): Promise<string> {\n const tables: RenderTable[] = config.tables;\n const modules = config.tableModules;\n\n const imports = [\n AUTOGEN_HEADER,\n \"\",\n 'import type { FormValidationRules, StorageItemType } from \"@orizm/consumer-sdk/common\";',\n 'import { type ConsumerClientOptions, OrizmConsumerClientBase } from \"@orizm/consumer-sdk\";',\n ].join(\"\\n\");\n\n const types = [\n renderSection(\"Tables\", tables.map(renderTableRowType)),\n modules.map(renderModuleRowTypeBlock).join(\"\\n\\n\"),\n renderSection(\"Descriptor types\", [\n ...tables.map(renderTableDescriptor),\n ...modules.map(renderModuleDescriptorBlock),\n ]),\n renderWebhookTypesSection(tables),\n ]\n .filter(Boolean)\n .join(\"\\n\\n\\n\");\n\n const source = [imports, UTILITIES, types, renderConsumerClient(config)].join(\n \"\\n\\n\\n\",\n );\n\n return formatTsWithPrettier(source);\n}\n\nfunction renderTableRowType(table: RenderTable): string {\n return renderTypeBlock(toCodeTypeName(table.name), [\n \"id: string;\",\n \"createdAt: string;\",\n \"updatedAt: string;\",\n \"group: string | null;\",\n \"publishedAt: string | null;\",\n \"_draft: boolean | null;\",\n \"_published: boolean | null;\",\n ...table.columns.map((col) => renderColumnField(col)),\n ...(table.enableForm ? [\"formSchema: FormValidationRules;\"] : []),\n ]);\n}\n\nfunction renderTableDescriptor(table: RenderTable): string {\n const name = toCodeTypeName(table.name);\n return renderTypeBlock(`${name}__Descriptor`, [\n `row: ${name};`,\n ...renderRefsFieldLines(table.columns),\n ...renderUniqueFieldLines(table),\n ...(table.enableDrafts ? [\"enableDrafts: true;\"] : []),\n ]);\n}\n\nfunction renderConsumerClient(config: CommonOrizmConfig): string {\n const tableEntries = config.tables\n .map(\n (t) =>\n `${t.name}: this.getTableClient<${toCodeTypeName(t.name)}__Descriptor>(\"${t.name}\"),`,\n )\n .join(\"\\n\");\n\n return `export class OrizmClient extends OrizmConsumerClientBase {\n constructor(options: ConsumerClientOptions) {\n super(options);\n }\n\n readonly tables = {\n ${tableEntries}\n };\n}`;\n}\n","import type { ArgsDef } from \"citty\";\nimport { defineCommand } from \"../define-command.js\";\nimport { contextArgs, configFileArg, DEFAULT_CONFIG_FILE } from \"../shared.js\";\nimport { renderConsumerModule } from \"../../codegen/consumer.js\";\nimport { runCodegen } from \"./run-codegen.js\";\n\nconst consumerArgs = {\n ...contextArgs,\n \"config-file\": configFileArg,\n output: {\n type: \"string\",\n alias: \"o\",\n description: \"Output file (.ts) or directory\",\n default: \"./src/orizm\",\n },\n pull: {\n type: \"boolean\",\n description:\n \"Generate from the server's applied definition instead of the local config\",\n default: false,\n },\n} satisfies ArgsDef;\n\nexport default defineCommand({\n meta: {\n name: \"consumer\",\n description: \"Generate Consumer SDK types from a schema definition\",\n },\n args: consumerArgs,\n run: ({ args }) =>\n runCodegen({\n args,\n pull: args.pull === true,\n configFile: args[\"config-file\"] ?? DEFAULT_CONFIG_FILE,\n output: args.output,\n label: \"Consumer\",\n render: renderConsumerModule,\n }),\n});\n"],"mappings":";;;;;AA0BA,SAAgB,qBACd,QACiB;CACjB,MAAM,SAAwB,OAAO;CACrC,MAAM,UAAU,OAAO;CAyBvB,OAAO,qBAJQ;EAnBC;GACd;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAce;EAAG;EAZX;GACZ,cAAc,UAAU,OAAO,IAAI,kBAAkB,CAAC;GACtD,QAAQ,IAAI,wBAAwB,CAAC,CAAC,KAAK,MAAM;GACjD,cAAc,oBAAoB,CAChC,GAAG,OAAO,IAAI,qBAAqB,GACnC,GAAG,QAAQ,IAAI,2BAA2B,CAC5C,CAAC;GACD,0BAA0B,MAAM;EAClC,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,QAEgC;EAAG,qBAAqB,MAAM;CAAC,CAAC,CAAC,KACvE,QAG+B,CAAC;AACpC;AAEA,SAAS,mBAAmB,OAA4B;CACtD,OAAO,gBAAgB,eAAe,MAAM,IAAI,GAAG;EACjD;EACA;EACA;EACA;EACA;EACA;EACA;EACA,GAAG,MAAM,QAAQ,KAAK,QAAQ,kBAAkB,GAAG,CAAC;EACpD,GAAI,MAAM,aAAa,CAAC,kCAAkC,IAAI,CAAC;CACjE,CAAC;AACH;AAEA,SAAS,sBAAsB,OAA4B;CACzD,MAAM,OAAO,eAAe,MAAM,IAAI;CACtC,OAAO,gBAAgB,GAAG,KAAK,eAAe;EAC5C,QAAQ,KAAK;EACb,GAAG,qBAAqB,MAAM,OAAO;EACrC,GAAG,uBAAuB,KAAK;EAC/B,GAAI,MAAM,eAAe,CAAC,qBAAqB,IAAI,CAAC;CACtD,CAAC;AACH;AAEA,SAAS,qBAAqB,QAAmC;CAQ/D,OAAO;;;;;;MAPc,OAAO,OACzB,KACE,MACC,GAAG,EAAE,KAAK,wBAAwB,eAAe,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,IACrF,CAAC,CACA,KAAK,IAQO,EAAE;;;AAGnB;;;;AC7FA,MAAM,eAAe;CACnB,GAAG;CACH,eAAe;CACf,QAAQ;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,SAAS;CACX;CACA,MAAM;EACJ,MAAM;EACN,aACE;EACF,SAAS;CACX;AACF;AAEA,uBAAe,cAAc;CAC3B,MAAM;EACJ,MAAM;EACN,aAAa;CACf;CACA,MAAM;CACN,MAAM,EAAE,WACN,WAAW;EACT;EACA,MAAM,KAAK,SAAS;EACpB,YAAY,KAAK;EACjB,QAAQ,KAAK;EACb,OAAO;EACP,QAAQ;CACV,CAAC;AACL,CAAC"}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
`orizm.config.ts` を読み込んで、スキーマをプロジェクトに適用します。
|
|
13
13
|
|
|
14
14
|
```sh copy
|
|
15
|
-
orizm schema push [<config-file>] [--dry-run] [--yes]
|
|
15
|
+
orizm schema push [<config-file>] [--dry-run] [--yes] [--force]
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
**引数**
|
|
@@ -27,8 +27,9 @@ orizm schema push [<config-file>] [--dry-run] [--yes]
|
|
|
27
27
|
| --- | --- |
|
|
28
28
|
| `--dry-run` | 適用せず、変更内容だけを表示します。 |
|
|
29
29
|
| `--yes` | 確認プロンプトをスキップして適用します(CI 向け)。 |
|
|
30
|
+
| `--force` | 変更が無くても定義を送り、サーバー側の突き合わせ(セマンティック検索のベクトルインデックスの再構築など)を再実行させます。`--dry-run` には影響しません。 |
|
|
30
31
|
|
|
31
|
-
適用前には変更内容が表示されます。`--dry-run` でも `--yes` でもないときは、ターミナルで確認プロンプトを出し、承認したときだけ適用します。非対話環境では `--yes`
|
|
32
|
+
適用前には変更内容が表示されます。`--dry-run` でも `--yes` でもないときは、ターミナルで確認プロンプトを出し、承認したときだけ適用します。非対話環境では `--yes` が必要です。変更が無いときは `--force` を付けない限り何もしません。
|
|
32
33
|
|
|
33
34
|
```sh copy
|
|
34
35
|
# 変更内容を確認する
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# CMS SDKのインストール
|
|
4
4
|
|
|
5
5
|
> [!NOTE]
|
|
6
|
-
> このドキュメントは `@orizm/cms-sdk` の **v2.
|
|
6
|
+
> このドキュメントは `@orizm/cms-sdk` の **v2.6.0-beta.1**
|
|
7
7
|
> に対応しています。プロジェクトにインストールされているバージョンが異なる場合、記載内容と実際の挙動が一致しないことがあります。
|
|
8
8
|
|
|
9
9
|
CMS SDKは、OrizmのCMS機能をWebサイトに組み込むためのJavaScriptライブラリです。このガイドでは、インストール手順とクライアントセットアップの方法を説明します。
|
|
@@ -41,6 +41,9 @@
|
|
|
41
41
|
| bucket.update | バケットオブジェクト更新 |
|
|
42
42
|
| bucket.delete | バケットオブジェクト削除 |
|
|
43
43
|
| storageItem.upload | ファイルアップロード |
|
|
44
|
+
| dictionary.add | 検索辞書エントリ登録 |
|
|
45
|
+
| dictionary.update | 検索辞書エントリ更新 |
|
|
46
|
+
| dictionary.delete | 検索辞書エントリ削除 |
|
|
44
47
|
| otpChallenge.success | ワンタイムパスワード・challenge 成功 |
|
|
45
48
|
| otpChallenge.tooManyAttempts | ワンタイムパスワード・challenge 試行回数が多すぎる |
|
|
46
49
|
| otpChallenge.invalid | ワンタイムパスワード・challenge OTPが無効な状態でAPIコール |
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Consumer SDKのインストール
|
|
4
4
|
|
|
5
5
|
> [!NOTE]
|
|
6
|
-
> このドキュメントは `@orizm/consumer-sdk` の **v2.
|
|
6
|
+
> このドキュメントは `@orizm/consumer-sdk` の **v2.6.0-beta.1**
|
|
7
7
|
> に対応しています。プロジェクトにインストールされているバージョンが異なる場合、記載内容と実際の挙動が一致しないことがあります。
|
|
8
8
|
|
|
9
9
|
Consumer SDKはOrizmのデータにアクセスするためのJavaScriptライブラリです。WebサイトやアプリケーションからOrizmのコンテンツを取得する際に使用します。
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
<!-- source: docs/src/app/features/dictionary/page.mdx -->
|
|
2
|
+
|
|
3
|
+
# 検索辞書
|
|
4
|
+
|
|
5
|
+
検索辞書を使用すると、社内の俗称や型番の表記ゆれを検索に教え込めます。開発コード「マニ丸」で検索した人に正式名称「全熱交換型換気システム」の記事を返す、といった言い換えを、コンテンツ本文を書き換えずに実現できます。
|
|
6
|
+
|
|
7
|
+
検索辞書は以下の機能を提供します。
|
|
8
|
+
|
|
9
|
+
- 同義語による検索クエリの言い換え(表記ゆれ・俗称の吸収)
|
|
10
|
+
- 用語そのものの解説を検索結果に返す
|
|
11
|
+
- プロジェクト全体に効く語彙管理(テーブルごとの設定は不要)
|
|
12
|
+
- エントリを削除せずに一時的に無効化
|
|
13
|
+
|
|
14
|
+
> [!WARNING]
|
|
15
|
+
> 検索辞書が検索に効くのは [セマンティック検索](./full-text-search.md)
|
|
16
|
+
> を有効にしたプロジェクトで、`mode` に `semantic` または `hybrid`
|
|
17
|
+
> を指定した検索だけです。`mode` を省略した検索(`keyword`)には効きません。
|
|
18
|
+
>
|
|
19
|
+
> セマンティック検索が利用できるかどうかは、プロジェクトの設定に加えてシステム側の設定でも決まります。システム側で有効になっていない環境では、辞書の登録・更新は成功しても検索には反映されません(`semantic` / `hybrid` がエラーになるか、`keyword` と同じ結果に劣化して返ります)。利用中の環境で使えるかは管理者に確認してください。
|
|
20
|
+
>
|
|
21
|
+
|
|
22
|
+
## ユースケース例
|
|
23
|
+
|
|
24
|
+
### 社内の俗称・略称で検索できるようにする
|
|
25
|
+
|
|
26
|
+
製品名や部署名には、正式名称のほかに現場でしか使われない呼び方があります。検索辞書に正式名称を見出し語、俗称を同義語として登録しておくと、どちらで検索しても同じコンテンツに当たります。コンテンツ側に俗称を書き足す必要はありません。
|
|
27
|
+
|
|
28
|
+
### 型番の表記ゆれを吸収する
|
|
29
|
+
|
|
30
|
+
`ORZ-1200X` のような型番は、全角で入力される・ハイフンが別の記号になるといった揺れが生まれます。この種の違いは [正規化](#表記の同一視) で自動的に吸収されますが、`ORZ 1200X` のように語の途中に空白が入る表記や、`オリズム1200` のようにまったく別の呼び方は吸収されないため、同義語として登録します。
|
|
31
|
+
|
|
32
|
+
### 用語集として検索結果に出す
|
|
33
|
+
|
|
34
|
+
説明を付けて登録したエントリは、それ自体が検索対象になります。編集者が社内用語で検索したときに、コンテンツの一覧と一緒に用語の解説を出せます。
|
|
35
|
+
|
|
36
|
+
## 前提
|
|
37
|
+
|
|
38
|
+
検索辞書そのものはプロジェクト単位の語彙で、辞書を登録するためのテーブルごとの設定はありません。ただし辞書が効くのは `semantic` / `hybrid` で検索できるテーブルに対してだけです。`orizm.config.ts` にプロジェクトの `semanticSearch` を宣言し、検索したいテーブルに `enableSearch: true` を付け、意味検索の対象にする string 列に `semanticSearch: true` を付けて `orizm schema push` してください([対象の列を指定する](./full-text-search.md#対象の列を指定するsemanticsearch-true))。
|
|
39
|
+
|
|
40
|
+
```ts copy filename="orizm.config.ts" showLineNumbers {4,8,9,11}
|
|
41
|
+
import { defineConfig } from "@orizm/cli/config";
|
|
42
|
+
|
|
43
|
+
export default defineConfig({
|
|
44
|
+
semanticSearch: { enabled: true },
|
|
45
|
+
tables: {
|
|
46
|
+
blog: {
|
|
47
|
+
columns: {
|
|
48
|
+
title: { type: "string", required: true, semanticSearch: true },
|
|
49
|
+
body: { type: "string", required: true, semanticSearch: true },
|
|
50
|
+
},
|
|
51
|
+
enableSearch: true,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
> [!NOTE]
|
|
58
|
+
> 検索辞書の操作は CMS SDK(および Management API)で行います。Orizm Console /
|
|
59
|
+
> Project Console には検索辞書の画面はありません。
|
|
60
|
+
|
|
61
|
+
## 2つの効き方
|
|
62
|
+
|
|
63
|
+
検索辞書は 2 つの経路で検索に作用します。エントリの内容によって、どちらが効くかが変わります。
|
|
64
|
+
|
|
65
|
+
| 経路 | 効く条件 | 反映タイミング |
|
|
66
|
+
| ---------------------------- | --------------------------------------------------------- | -------------- |
|
|
67
|
+
| 同義語によるクエリの言い換え | `hybrid` 検索。同義語が 1 つ以上あるエントリ | 即時 |
|
|
68
|
+
| 用語解説を検索結果に返す | CMS SDK の `semantic` / `hybrid` 検索。説明があるエントリ | 非同期 |
|
|
69
|
+
|
|
70
|
+
どちらも `enabled: false` のエントリには効きません。
|
|
71
|
+
|
|
72
|
+
### 同義語によるクエリの言い換え
|
|
73
|
+
|
|
74
|
+
`hybrid` で検索すると、クエリの中に辞書の表記が含まれていた場合に、それを同じエントリの別表記へ置き換えた「変種クエリ」が検索に足されます。置き換えは見出し語と同義語の双方向で、見出し語で検索すれば各同義語に、同義語で検索すれば見出し語と他の同義語に置き換わります。
|
|
75
|
+
|
|
76
|
+
例えば見出し語 `ORZ-1200X`、同義語 `オリズム1200` / `1200X` のエントリがある場合、`オリズム1200 の仕様` というクエリからは `orz-1200x の仕様` と `1200x の仕様` が足されます。
|
|
77
|
+
|
|
78
|
+
元のクエリは必ず検索対象として残るので、辞書を登録して検索に一致しなくなるコンテンツはありません。ただし順位は変わります。`hybrid` は上位 100 件までの窓で順位を融合して返すため、言い換えで新たに一致したコンテンツが加わるとその分だけ既存のヒットの順位が下がり、一致の多いクエリでは窓から外れて表示されなくなることがあります。
|
|
79
|
+
|
|
80
|
+
この経路は Consumer SDK の `hybrid` 検索でも同じように効きます。ただしどのエントリが効いたのかは検索結果に現れません。
|
|
81
|
+
|
|
82
|
+
ベクトル検索側の障害やシステム側の停止でキーワード検索に劣化したリクエストでは、言い換えも効きません(劣化した応答は `keyword` で検索したときと同じ結果になります)。
|
|
83
|
+
|
|
84
|
+
> [!NOTE]
|
|
85
|
+
> 照合はクエリ文字列に対する部分一致で、単語の区切りは見ません。短い表記を登録すると、それを含む別の語にも言い換えが起きます。
|
|
86
|
+
>
|
|
87
|
+
> 1 つの変種クエリで置き換えるのは 1 エントリの 1 表記だけです。クエリの中の 2
|
|
88
|
+
> 語がどちらも別表記で書かれているコンテンツは拾えないことがあります。
|
|
89
|
+
>
|
|
90
|
+
> 1 回の検索で足される変種クエリは最大 20 件です。また言い換えに使われるのは、同義語を持つ有効なエントリのうち登録が古い順に
|
|
91
|
+
> 5,000 件までで、これを超える分は効きません(説明だけのエントリはこの数に含まれません)。
|
|
92
|
+
>
|
|
93
|
+
|
|
94
|
+
### 用語解説を検索結果に返す
|
|
95
|
+
|
|
96
|
+
説明(`description`)を付けたエントリは、それ自体が検索対象になります。CMS SDK で `semantic` または `hybrid` の検索をすると、検索結果に `_dictionary` が付き、クエリに近いものから最大 3 件の用語解説が返ります。クエリと関連の薄いエントリは含まれないので、辞書のエントリが少なくても無関係な用語解説が並ぶことはありません。
|
|
97
|
+
|
|
98
|
+
```ts copy
|
|
99
|
+
const result = await cmsClient.tables.blog.search({
|
|
100
|
+
query: "熱を回収する換気",
|
|
101
|
+
mode: "hybrid",
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
console.log(result.contents); // コンテンツのヒット
|
|
105
|
+
console.log(result._dictionary); // 辞書のヒット(最大 3 件)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`_dictionary` の各要素は以下のフィールドを持ちます。
|
|
109
|
+
|
|
110
|
+
| フィールド | 説明 |
|
|
111
|
+
| ------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
112
|
+
| `id` | エントリの ID。`get()` / `update()` / `delete()` にそのまま渡せます |
|
|
113
|
+
| `term` | 見出し語(登録した表記のまま) |
|
|
114
|
+
| `description` | 説明 |
|
|
115
|
+
| `score` | クエリと、見出し語・同義語・説明をつないだ文章との近さ。行の `_semantic.score` とは尺度が違うため比較できません |
|
|
116
|
+
|
|
117
|
+
照合に使われるのは説明だけではありません。見出し語と同義語も同じ文章に含めて突き合わせるため、説明に俗称を書かなくても、俗称で検索したときに当たりやすくなります。
|
|
118
|
+
|
|
119
|
+
辞書のヒットは `contents` とは別の枠で返り、`totalCount` にも含まれません。ページングもせず、`offset` を動かしても同じ内容が返ります。
|
|
120
|
+
|
|
121
|
+
辞書のヒットには近さの下限がありません。説明付きの有効なエントリが 3 件以上あるプロジェクトでは、辞書と関係の薄いクエリでも近い順に 3 件が埋まります。そのまま画面に出すと常に 3 件並ぶので、出すかどうかは `score` を見て呼び出し側で決めてください(`score` の目安になる値は埋め込みモデルによって変わるため、決め打ちのしきい値は用意していません)。
|
|
122
|
+
|
|
123
|
+
`_dictionary` は状態によって 3 通りになります。
|
|
124
|
+
|
|
125
|
+
- **キーが無い**: `keyword` 検索、キーワード検索への劣化時、有効な説明付きのエントリが 1 つも無いプロジェクト(反映待ちの間を含む)、辞書の検索が一時的に失敗したとき、どのテーブルも読めないキーでの検索
|
|
126
|
+
- **空配列**: 辞書は引けたが返せるエントリが無かった(通常は起きません)
|
|
127
|
+
- **配列**: ヒットあり
|
|
128
|
+
|
|
129
|
+
キーの有無は設定だけで決まるものではないため、`_dictionary` は常に省略され得るものとして扱ってください。
|
|
130
|
+
|
|
131
|
+
> [!WARNING]
|
|
132
|
+
> 辞書のヒットにはグループによる権限のフィルタが掛かりません(付くかどうかは、プロジェクト内のいずれかのテーブルを読めるキーかどうかだけで決まります)。特定のグループにだけ見せたい情報は説明に書かないでください。
|
|
133
|
+
>
|
|
134
|
+
> Consumer SDK の検索には `_dictionary`
|
|
135
|
+
> は付きません。辞書エントリには公開・下書きの区別が無いためです。
|
|
136
|
+
>
|
|
137
|
+
|
|
138
|
+
## 表記の同一視
|
|
139
|
+
|
|
140
|
+
エントリは見出し語を正規化した値で識別されます。表記が違っても正規化後に同じなら同じエントリで、検索時の照合にも同じ正規化が使われます。
|
|
141
|
+
|
|
142
|
+
以下の違いは同じ語として扱われます。
|
|
143
|
+
|
|
144
|
+
- 全角と半角(`ORZ-1200X` = `orz-1200x`)
|
|
145
|
+
- 大文字と小文字
|
|
146
|
+
- 半角カナと全角カナ(`オリズム` = `オリズム`)
|
|
147
|
+
- ハイフン・マイナス・ダッシュ類(`ORZ‐1200X` = `ORZ−1200X` = `orz-1200x`)
|
|
148
|
+
- 前後の空白、連続する空白、全角空白
|
|
149
|
+
- 貼り付けで紛れ込む不可視文字(ゼロ幅スペースなど)
|
|
150
|
+
|
|
151
|
+
長音記号 `ー` はハイフンに畳まないため、`コーヒー` と `コ-ヒ-` は別の語です。
|
|
152
|
+
|
|
153
|
+
見出し語と同義語は入力した表記のまま保存・返却され、正規化した値は検索の照合にだけ使われます。なお同義語のうち、正規化すると見出し語と同じになるもの・先に指定した同義語と同じになるものは、登録時に取り除かれます。
|
|
154
|
+
|
|
155
|
+
## 使い方
|
|
156
|
+
|
|
157
|
+
CMS SDK の `cmsClient.dictionary` から操作します。テーブルの配下ではなくクライアント直下にあります。
|
|
158
|
+
|
|
159
|
+
辞書の登録・更新・削除には、プロジェクト内のいずれかのテーブルへの書き込み権限が必要です([権限](./schema/authority.md) でどのテーブルにも書けないロールでは 403 になります)。一覧・取得には、プロジェクト内のいずれかのテーブルへの読み取り権限が必要です(どのテーブルも読めないロールでは 403 になります)。
|
|
160
|
+
|
|
161
|
+
### エントリの登録
|
|
162
|
+
|
|
163
|
+
`add()` に登録したいエントリの配列を渡します。1 回のリクエストで複数のエントリを登録できます。
|
|
164
|
+
|
|
165
|
+
```ts copy
|
|
166
|
+
await cmsClient.dictionary.add([
|
|
167
|
+
{
|
|
168
|
+
term: "全熱交換型換気システム",
|
|
169
|
+
synonyms: ["マニ丸", "ロスナイ式"],
|
|
170
|
+
description: "熱交換素子で温度と湿度を回収しながら換気する第一種換気設備。",
|
|
171
|
+
},
|
|
172
|
+
]);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`description` と `synonyms` は省略できます。`enabled` を `false` にすると、登録はしても検索には効かない状態で作れます(既定は `true`)。
|
|
176
|
+
|
|
177
|
+
> [!WARNING]
|
|
178
|
+
> `add()` は、正規化した見出し語が既存のエントリと一致した場合そのエントリを**丸ごと置き換えます**。渡さなかったフィールドは前の値のままにはならず、初期値に戻ります(`synonyms`
|
|
179
|
+
> は `[]`、`description` は `null`、`enabled` は `true`)。
|
|
180
|
+
>
|
|
181
|
+
> 一部のフィールドだけを変えたいときは [`update()`](#エントリの部分更新)
|
|
182
|
+
> を使ってください。
|
|
183
|
+
>
|
|
184
|
+
> 置き換えになるので、同じ一覧を投入し直しても重複したエントリは作られません。ID
|
|
185
|
+
> も変わらないので、`_dictionary` などで受け取った ID
|
|
186
|
+
> は投入し直したあとも使えます。一方、1 回のリクエストに同じ見出し語を 2
|
|
187
|
+
> つ入れることはできません(エラーになります)。
|
|
188
|
+
>
|
|
189
|
+
|
|
190
|
+
### エントリの一覧取得
|
|
191
|
+
|
|
192
|
+
`list()` でエントリの一覧を取得します。登録が古い順に返り、`enabled: false` のエントリも含まれます。
|
|
193
|
+
|
|
194
|
+
```ts copy
|
|
195
|
+
const { contents, totalCount } = await cmsClient.dictionary.list();
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`query` で絞り込み、`limit` と `offset` でページングできます。
|
|
199
|
+
|
|
200
|
+
```ts copy
|
|
201
|
+
await cmsClient.dictionary.list({ query: "換気", limit: 50, offset: 0 });
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
`query` の当たり方は見出し語と同義語で違います。見出し語は部分一致、同義語は完全一致です。どちらも正規化して突き合わせるので、半角で登録した語を全角で検索できます。正規化して空になる値(空白のみなど)は未指定と同じ扱いで、絞り込みません。
|
|
205
|
+
|
|
206
|
+
`limit` を指定しない場合は 100 件まで取得されます。
|
|
207
|
+
|
|
208
|
+
### エントリの取得
|
|
209
|
+
|
|
210
|
+
`get()` に ID を渡して 1 件を取得します。
|
|
211
|
+
|
|
212
|
+
```ts copy
|
|
213
|
+
const entry = await cmsClient.dictionary.get(entryId);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### エントリの部分更新
|
|
217
|
+
|
|
218
|
+
`update()` は渡したフィールドだけを変更します。渡さなかったフィールドは変わりません。
|
|
219
|
+
|
|
220
|
+
```ts copy
|
|
221
|
+
await cmsClient.dictionary.update(entryId, { synonyms: ["マニ丸", "1200X"] });
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
`description` に `null` を渡すと説明を消せます。説明が無くなったエントリは検索結果に返らなくなりますが、同義語による言い換えは引き続き効きます。
|
|
225
|
+
|
|
226
|
+
```ts copy
|
|
227
|
+
await cmsClient.dictionary.update(entryId, { description: null });
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
一時的に効果を止めたいときは `enabled` を `false` にします。削除せずに両方の経路を止められます。
|
|
231
|
+
|
|
232
|
+
```ts copy
|
|
233
|
+
await cmsClient.dictionary.update(entryId, { enabled: false });
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
`term` を変えると、エントリを識別する値も一緒に変わります。変更後の表記が既にある別のエントリと同じになる場合はエラーになります。このとき同義語も組み直されるため、新しい見出し語と同じになる同義語は(`synonyms` を渡していなくても)取り除かれます。
|
|
237
|
+
|
|
238
|
+
### エントリの削除
|
|
239
|
+
|
|
240
|
+
`delete()` に ID を渡します。
|
|
241
|
+
|
|
242
|
+
```ts copy
|
|
243
|
+
await cmsClient.dictionary.delete(entryId);
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## 検索への反映タイミング
|
|
247
|
+
|
|
248
|
+
同義語による言い換えは、登録・更新した直後の検索から効きます。
|
|
249
|
+
|
|
250
|
+
用語解説の検索対象化(`_dictionary`)は非同期です。エントリを変更すると裏で辞書の索引が作り直され、それが終わってから検索結果に現れます。所要時間は説明付きのエントリの件数によって変わります。無効化・削除で検索結果から消える場合も同じ経路を通ります。
|
|
251
|
+
|
|
252
|
+
説明付きの有効なエントリが 1 つも無くなると辞書の索引自体が削除され、以降の検索では `_dictionary` が付かなくなります。
|
|
253
|
+
|
|
254
|
+
## 上限値
|
|
255
|
+
|
|
256
|
+
| 対象 | 上限 |
|
|
257
|
+
| ------------------------------------- | ------------------ |
|
|
258
|
+
| 1 回の `add()` で登録できるエントリ数 | 500 件(1 件以上) |
|
|
259
|
+
| 見出し語・同義語 1 つあたりの文字数 | 200 文字 |
|
|
260
|
+
| 1 エントリの同義語の数 | 50 個 |
|
|
261
|
+
| 説明の文字数 | 2000 文字 |
|
|
262
|
+
| `list()` の `limit` | 500(既定 100) |
|
|
263
|
+
|
|
264
|
+
見出し語・同義語・説明には制御文字を含められません(タブ・改行・復帰は除きます。説明は複数行で登録できます。見出し語・同義語では空白に畳まれます)。また空白だけの見出し語・同義語・説明は登録できません。
|
|
265
|
+
|
|
266
|
+
## 監査ログ
|
|
267
|
+
|
|
268
|
+
エントリの登録・更新・削除は [監査ログ](./console/audit-logs.md) に記録されます。
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<!-- source: docs/src/app/features/full-text-search/local-development/page.mdx -->
|
|
2
|
+
|
|
3
|
+
# セマンティック検索をローカルで動かす
|
|
4
|
+
|
|
5
|
+
Orizm をローカルで動かして開発するときに、[セマンティック検索](../full-text-search.md#検索モードセマンティック検索)(`mode: "semantic"` / `"hybrid"`)と [検索辞書](../dictionary.md) を手元で試す手順です。外部サービスは使わず、`docker compose` の OpenSearch だけで動きます。
|
|
6
|
+
|
|
7
|
+
> [!NOTE]
|
|
8
|
+
> この記事は Orizm 本体をローカルで起動する人(セルフホストや Orizm
|
|
9
|
+
> 自体の開発)向けです。マネージドの
|
|
10
|
+
> Orizm(app.orizm.com)を使っている場合、この手順は不要で、[プロジェクトの有効化](../full-text-search.md#検索モードセマンティック検索)だけで利用できます。
|
|
11
|
+
|
|
12
|
+
## 前提
|
|
13
|
+
|
|
14
|
+
Orizm 本体の開発環境が、リポジトリの README のセットアップ手順どおりに動いていることが前提です。具体的には `pnpm install`、`pnpm run generate`(Prisma クライアントなどの生成コード)、`pnpm run build --filter='./packages/*'`(ワークスペース内パッケージのビルド。`pnpm run dev` を一度起動していれば作られています)が済んでいて、DB を初期化し、開発者コンソールにログインできる状態です。以降の手順はその環境にセマンティック検索を足すものです。clone 直後の状態で手順 3 を実行すると、生成コードやパッケージのビルド成果物が無いためモジュールが見つからないエラーで止まります。また、パッケージをビルドしたあとに `pnpm install` を一度実行し直さないと `orizm` コマンドがリンクされず、手順 5 の push が `orizm: command not found` になります。
|
|
15
|
+
|
|
16
|
+
## 仕組み
|
|
17
|
+
|
|
18
|
+
既定の `ORIZM_EMBEDDING_SEARCH=off` では、検索は `keyword`(全文検索)だけが動き、ベクトルインデックスは作られません。`local` にすると、埋め込みの推論を OpenSearch クラスタ内のローカルモデル(多言語 MiniLM・384 次元)で行います。`docker compose` の OpenSearch は公式イメージがベースで、必要なプラグイン(ml-commons / k-NN / neural-search)は同梱されているため、追加のコンテナは要りません。
|
|
19
|
+
|
|
20
|
+
本番方針の Amazon Bedrock(`bedrock`)はローカルから到達できないので、本番と同じ経路での確認はステージング以降で行います。
|
|
21
|
+
|
|
22
|
+
## 手順
|
|
23
|
+
|
|
24
|
+
### 1. 推論経路を `local` にする
|
|
25
|
+
|
|
26
|
+
`apps/server/.env` に以下を設定します。
|
|
27
|
+
|
|
28
|
+
```bash filename="apps/server/.env"
|
|
29
|
+
ORIZM_EMBEDDING_SEARCH=local
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
> [!WARNING]
|
|
33
|
+
> 同じキーを `.env` の中に 2 回書かないでください。dotenv
|
|
34
|
+
> は後に書いた値が勝つため、重複していると意図しない値が黙って効きます。
|
|
35
|
+
|
|
36
|
+
### 2. OpenSearch を起動する
|
|
37
|
+
|
|
38
|
+
```bash copy
|
|
39
|
+
docker compose up
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 3. 埋め込み基盤を用意する
|
|
43
|
+
|
|
44
|
+
DB のマイグレーションを当てたあと、埋め込みモデルの登録・配備と取り込みパイプラインの作成を行います。名前が似ていますが別のコマンドで、順番はこのとおりです。
|
|
45
|
+
|
|
46
|
+
```bash copy
|
|
47
|
+
pnpm run -F ./apps/server dev:migrate # DB のテーブル定義(Prisma)
|
|
48
|
+
pnpm run -F ./apps/server dev:migration # Content Plane と埋め込み基盤の同期
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
どちらも冪等で、再実行時は既存のものを再利用します。初回はモデルのダウンロードに数分かかります(待機の上限は 10 分)。ログに次の行が出れば完了です。
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
[semanticSearch] embedding infrastructure is ready
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 4. サーバーとワーカーを起動する
|
|
58
|
+
|
|
59
|
+
```bash copy
|
|
60
|
+
pnpm run dev
|
|
61
|
+
pnpm dev:sandbox # 動作確認に sandbox を使う場合は別ターミナルで
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`pnpm run dev` には手順 3 の `dev:migration` は含まれません(本番でもマイグレーションはサーバーやワーカーとは別のタスクとして先に実行されます)。起動時のバナーの `EmbeddingSearch:` 行で、現在の推論経路を確認できます。
|
|
65
|
+
|
|
66
|
+
### 5. プロジェクトで有効にする
|
|
67
|
+
|
|
68
|
+
セマンティック検索は、システム側の設定(手順 1)とプロジェクト側の設定の両方が有効なときだけ動きます。`orizm.config.ts` に `semanticSearch` を宣言し、検索したいテーブルに `enableSearch: true` を付け、意味検索の対象にする string 列に `semanticSearch: true` を付けて push します(対象列の無いテーブルにはベクトルインデックスが作られず、`semantic` / `hybrid` は 403 になります。詳しくは [対象の列を指定する](../full-text-search.md#対象の列を指定するsemanticsearch-true))。
|
|
69
|
+
|
|
70
|
+
```ts copy filename="orizm.config.ts" showLineNumbers {4,8,9,11}
|
|
71
|
+
import { defineConfig } from "@orizm/cli/config";
|
|
72
|
+
|
|
73
|
+
export default defineConfig({
|
|
74
|
+
semanticSearch: { enabled: true },
|
|
75
|
+
tables: {
|
|
76
|
+
article: {
|
|
77
|
+
columns: {
|
|
78
|
+
title: { type: "string", required: true, semanticSearch: true },
|
|
79
|
+
body: { type: "string", required: true, semanticSearch: true },
|
|
80
|
+
},
|
|
81
|
+
enableSearch: true,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
同梱の sandbox-cms は宣言済みです。`orizm` CLI は `.env` を読まないので、開発者キーとプロジェクト名を環境変数で渡して push します([認証](../cli/authentication.md)・[プロジェクトのリンク](../cli/project-linking.md)。`orizm auth login` と `orizm link` で済ませてもかまいません)。非対話シェルでは確認プロンプトを出せないので `--yes` を付けます。
|
|
88
|
+
|
|
89
|
+
```bash copy
|
|
90
|
+
ORIZM_API_KEY=<開発者キー> ORIZM_PROJECT=demo pnpm run -F ./apps/sandbox-cms orizm:push --yes
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
初期化スクリプトが作る demo プロジェクトの開発者キーは README の「Orizm Console」節にあります。環境変数なしで実行すると次のエラーで止まります。
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
Not authenticated. Run `orizm auth login`, or set ORIZM_API_KEY.
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
push すると `semanticSearch: true` の列を持つテーブルにベクトルインデックスが作られ、既存コンテンツの埋め込み(再構築)がワーカーで非同期に実行されます。
|
|
100
|
+
|
|
101
|
+
### 6. 動かして確かめる
|
|
102
|
+
|
|
103
|
+
- sandbox の検索画面で mode を切り替えて結果を見比べます。CMS SDK 経由は http://localhost:8000/admin/articles/search 、Consumer SDK 経由は http://localhost:8001/articles/search です
|
|
104
|
+
- 開発者コンソールのテーブル画面にある検索インデックスに `published_vector`(`enableDrafts` のテーブルでは `draft_vector` も)が出ていて、ドキュメント数が増えていれば埋め込みは作られています
|
|
105
|
+
- `semantic` / `hybrid` の結果の各行に `_semantic` が付いていれば、ベクトル検索が実際に動いています(付いていなければ、後述の劣化の状態です)
|
|
106
|
+
|
|
107
|
+
## 注意点
|
|
108
|
+
|
|
109
|
+
### 手順 3 を飛ばすと動かない
|
|
110
|
+
|
|
111
|
+
埋め込み基盤が無い状態でサーバーを起動すると、書き込み時のベクトル同期は失敗して再試行待ち(DLQ)に落ち、`semantic` / `hybrid` の検索は `search index is not ready` のエラー(403)で拒否されます。サーバーとワーカーは起動時に基盤を確認し、モデルが配備されていなければ次の error ログを出します。
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
[semanticSearch] ORIZM_EMBEDDING_SEARCH is set but no deployed embedding model was found
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
これが出たら手順 3 を実行してから起動し直してください。推論経路やモデルの設定を変えたときも同様です。
|
|
118
|
+
|
|
119
|
+
### 有効化の直後は 403 になる
|
|
120
|
+
|
|
121
|
+
プロジェクトを有効化した直後や、テーブルの列に `semanticSearch: true` を新しく付けた(または付け外しした)直後は、既存コンテンツ全件の埋め込みを作り直す再構築が走ります。完了するまで `semantic` / `hybrid` は 403 になり、完了すると使えるようになります。所要時間はコンテンツ量に比例します。`semanticSearch: true` の列が 1 つも無いテーブルはベクトルインデックス自体が作られず、`semantic` / `hybrid` は `search index not found (no column has semanticSearch: true)` の 403 になります。
|
|
122
|
+
|
|
123
|
+
### 本番とスコアは一致しない
|
|
124
|
+
|
|
125
|
+
ローカル(MiniLM・384 次元)と本番(Bedrock・Titan・1024 次元)では埋め込みモデルが違います。スコアの絶対値や順位、多言語の当たり方はローカルと本番で一致しません。検索の品質や、[検索辞書](../dictionary.md) の効き方の最終確認は、本番と同じ推論経路のステージング環境で行ってください。
|
|
126
|
+
|
|
127
|
+
### 埋め込み基盤が応答しないと `keyword` に劣化する
|
|
128
|
+
|
|
129
|
+
ベクトルインデックスができたあとで埋め込みの推論が失敗・タイムアウトすると、検索は失敗せずに `keyword` の結果に劣化して 200 を返します。このとき各行の `_semantic` と `_dictionary` は付きません。ローカルで「セマンティック検索が効いていない」と感じたら、まず `_semantic` の有無と OpenSearch のログを確認してください。
|
|
130
|
+
|
|
131
|
+
### OpenSearch のメモリ
|
|
132
|
+
|
|
133
|
+
モデルの推論も OpenSearch のコンテナ内で行うため、メモリが足りないと OpenSearch が落ちたり推論がタイムアウトしたりします。`compose.yaml` の既定は JVM ヒープ 512MB(`OPENSEARCH_JAVA_OPTS`)です。不安定な場合は Docker のメモリ割り当てと合わせて増やしてください。
|
|
134
|
+
|
|
135
|
+
### `off` に戻すのは非破壊
|
|
136
|
+
|
|
137
|
+
`ORIZM_EMBEDDING_SEARCH=off` に戻しても、既存のベクトルインデックスと埋め込み済みデータは残り、埋め込みの生成(書き込み時の同期と再構築)だけが止まります。この間の `semantic` / `hybrid` は `keyword` に劣化して応答します。`local` に戻してワーカーを起動すると、止まっていた間に古くなったインデックスは起動時の突き合わせで自動的に再構築されます。
|
|
138
|
+
|
|
139
|
+
### 古いモデルは自動では消えない
|
|
140
|
+
|
|
141
|
+
モデルや次元の設定を変えると、新しい名前のモデルが登録され、古いモデルは OpenSearch に残ります。ml-commons の API(`POST /_plugins/_ml/models/_search`)で登録済みのモデルを確認し、不要になったものは undeploy してから削除してください。
|
|
142
|
+
|
|
143
|
+
### 突き合わせだけをやり直す
|
|
144
|
+
|
|
145
|
+
ワーカーを再起動せず、定義も変えないまま、サーバー側の突き合わせ(ベクトルインデックスの再構築など)だけを再実行したいときは、`orizm schema push` に [`--force`](../cli/commands/schema.md#orizm-schema-push) を付けます。差分が無くても定義が送られ、突き合わせが走ります。
|