/** * WPML compatibility functions * * @global array $duplicated_posts Array to store the posts being duplicated. * * @package Yoast\WP\Duplicate_Post * @since 3.2 */ add_action( 'admin_init', 'duplicate_post_wpml_init' ); /** * Add handlers for WPML compatibility. */ function duplicate_post_wpml_init() { if ( defined( 'ICL_SITEPRESS_VERSION' ) ) { add_action( 'dp_duplicate_page', 'duplicate_post_wpml_copy_translations', 10, 3 ); add_action( 'dp_duplicate_post', 'duplicate_post_wpml_copy_translations', 10, 3 ); add_action( 'shutdown', 'duplicate_wpml_string_packages', 11 ); } } global $duplicated_posts; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: Renaming a global variable is a BC break. $duplicated_posts = []; /** * Copy post translations. * * @global SitePress $sitepress Instance of the Main WPML class. * @global array $duplicated_posts Array of duplicated posts. * * @param int $post_id ID of the copy. * @param WP_Post $post Original post object. * @param string $status Status of the new post. */ function duplicate_post_wpml_copy_translations( $post_id, $post, $status = '' ) { global $sitepress; global $duplicated_posts; remove_action( 'dp_duplicate_page', 'duplicate_post_wpml_copy_translations', 10 ); remove_action( 'dp_duplicate_post', 'duplicate_post_wpml_copy_translations', 10 ); $current_language = $sitepress->get_current_language(); $trid = $sitepress->get_element_trid( $post->ID ); if ( ! empty( $trid ) ) { $translations = $sitepress->get_element_translations( $trid ); $new_trid = $sitepress->get_element_trid( $post_id ); foreach ( $translations as $code => $details ) { if ( $code !== $current_language ) { if ( $details->element_id ) { $translation = get_post( $details->element_id ); if ( ! $translation ) { continue; } $new_post_id = duplicate_post_create_duplicate( $translation, $status ); if ( ! is_wp_error( $new_post_id ) ) { $sitepress->set_element_language_details( $new_post_id, 'post_' . $translation->post_type, $new_trid, $code, $current_language ); } } } } // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: see above. $duplicated_posts[ $post->ID ] = $post_id; } } /** * Duplicate string packages. * * @global array() $duplicated_posts Array of duplicated posts. */ function duplicate_wpml_string_packages() { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: renaming the function would be a BC-break. global $duplicated_posts; foreach ( $duplicated_posts as $original_post_id => $duplicate_post_id ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: using WPML native filter. $original_string_packages = apply_filters( 'wpml_st_get_post_string_packages', false, $original_post_id ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: using WPML native filter. $new_string_packages = apply_filters( 'wpml_st_get_post_string_packages', false, $duplicate_post_id ); if ( is_array( $original_string_packages ) ) { foreach ( $original_string_packages as $original_string_package ) { $translated_original_strings = $original_string_package->get_translated_strings( [] ); foreach ( $new_string_packages as $new_string_package ) { $cache = new WPML_WP_Cache( 'WPML_Package' ); $cache->flush_group_cache(); $new_strings = $new_string_package->get_package_strings(); foreach ( $new_strings as $new_string ) { if ( isset( $translated_original_strings[ $new_string->name ] ) ) { foreach ( $translated_original_strings[ $new_string->name ] as $language => $translated_string ) { do_action( // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: using WPML native filter. 'wpml_add_string_translation', $new_string->id, $language, $translated_string['value'], $translated_string['status'] ); } } } } } } } } 工程4:外部連携クライアントの確定(Dev-Portal / DeciKG) – Raqqa

工程4:外部連携クライアントの確定(Dev-Portal / DeciKG)

目的

nlq-dev は SQL/Cypher を生成しない
nlq-dev は params(sql_params / decikg_params)だけを外部へ渡し、外部側(Dev-Portal / DeciKG)で生成・実行する。
→ nlq-dev の責務は「ルーティング・params整形・結果の表示/分析のための共通フォーマット化」に限定する。


0) 工程4の“前提”としての決定事項(ユーザー指定)

  1. DeciKG は情報を取りにいかない(Auraベース)
    • DeciKG(Aura)側から Dev-Portal/Odoo に pull しない。
    • 必要な情報の投入は AWS側(将来の feeder 等)から push/upsert のみ。
  2. Dev-Portal は本番環境を利用
    • Dev-Portal の接続仕様・エンドポイント・Auth は、GitHub上の実体をあなたが提示し、それに合わせて nlq-dev のクライアントを実装する。
  3. DeciKG は一旦オフショアへハンドオフしてから開発開始(Auraで)
    • ただし Dev-Portal フロント開発が先行するため、DeciKG 側I/Fが間に合わない可能性を考慮し、stub で先に開発できる構造にする。
    • 後から Aura接続へ最小差分で切替できるようにしておく。

4-A) Dev-Portal 側(SqlExecutor)

決定事項(I/F固定)

  • nlq-dev → Dev-Portal に渡すのは SQL文字列ではなく sql_params
  • Dev-Portal 側が SQL生成 + 安全実行(もしくは既存 /ask/sql の “params実行モード” を利用)
  • nlq-dev は max_rows / dry_run / timeout などの実行ガードだけ渡す(SQL安全性の本体は Dev-Portal)

リクエスト/レスポンス(最低限の契約)

  • request: { sql_params: {...}, max_rows, dry_run }
  • response: tabular_result(例:columns[], rows[], row_count, truncated, warnings[], trace_id

“sql_params の具体スキーマ”は Dev-Portal 実装(あなたが提示するGitHub)に合わせる。nlq-dev は型を“ゆるく”受けて、互換性優先。

想定変更ファイル(nlq-dev)

  • 既に Dev-Portal 呼び出しがある場合
    • services/sql_executor.py(または相当)
      • 「SQL生成」処理を削除/無効化し、sql_params を Dev-Portal client に渡す
    • services/router.py
      • route=SQL_ONLY の場合でも、最終実行は Dev-Portal に委譲する形に統一

新規ファイル候補(nlq-dev)

  • services/dev_portal_client.py
    • health() -> bool
    • execute_sql_params(sql_params, *, max_rows=..., dry_run=...) -> TabularResult
  • schemas/dev_portal.py
    • TabularResult, DevPortalError など “最低限” の型(columns/rows/warnings/trace_id)

4-B) DeciKG 側(CypherExecutor)

決定事項(I/F固定)

  • nlq-dev → DeciKG に渡すのは Cypher文字列ではなく decikg_params
  • DeciKG 側で Cypher生成 + 実行(Aura接続)
  • 戻りは nlq-dev が扱いやすい graph_result(例:nodes/edges/evidence/summary)

stub 前提(間に合わない場合の開発継続)

  • デフォルトは stub で動く(=UI/フロントは止めない)
  • 後から DECIGK_MODE=http(or aura)に変えるだけで接続できる
  • 重要:nlq-dev 内部の “分析/表示” は graph_result の形に依存させ、実装(stub/http)に依存させない

想定変更ファイル(nlq-dev)

  • 既存の Neo4j 直結がある場合
    • services/graph_client.py(Neo4j driver 直結をやめ、HTTPのDeciKG client へ寄せる)
    • services/router.py
      • route=CYPHER_ONLY / CYPHER_THEN_SQL でも “Cypher生成” はしない。decikg_params を作って client に渡すだけ。

新規ファイル候補(nlq-dev)

  • services/decikg_client.pygraph_client を置換する想定)
    • health() -> bool
    • query(decikg_params) -> GraphResult
    • concept_lookup(text) -> candidates(必要なら)
  • schemas/decikg.py
    • GraphResult(nodes/edges/evidence/summary、最低限でOK)
  • services/decikg_stub.py(stub実装を分離するなら)
    • query() がダミーの graph_result を返す(UI開発継続用)

DoD(工程4の合格条件)

I/F固定(仕様)

  • nlq-dev は SQL/Cypher文字列を外部へ渡さない
    • Dev-Portal: sql_params のみ
    • DeciKG: decikg_params のみ
  • 返却形式は nlq-dev 側で扱う共通形式に正規化
    • tabular_result / graph_result

環境変数(例:最低限)

  • Dev-Portal
    • DEVPORTAL_URL
    • DEVPORTAL_API_KEY(必要なら)
  • DeciKG
    • DECIGK_MODE=dummy|http(まず dummy)
    • DECIGK_URL(http のとき)
    • DECIGK_API_KEY(必要なら)

疎通確認

  • dev_portal_client.health() が HTTP 200 相当で成功する
  • decikg_client.health()
    • dummy の場合:常に成功(または明示的に “dummy ok”)
    • http の場合:HTTP 200 相当で成功する
  • stub が有効な場合、外部が落ちていても nlq-dev が落ちない(フォールバックできる)

新規/変更ファイル一覧(工程4のアウトプット)

変更(想定)

  • services/sql_executor.py(または相当):SQL生成をやめて Dev-Portal client 呼び出しへ
  • services/router.py:route決定後の実行を params 委譲に統一
  • services/graph_client.py(存在するなら):直結廃止して DeciKG client へ移行

新規(候補)

  • services/dev_portal_client.py
  • schemas/dev_portal.py
  • services/decikg_client.py
  • schemas/decikg.py
  • (必要なら)services/decikg_stub.py

この工程4の次の作業(工程5以降)に直結するので、あなたが GitHub で見つける **Dev-Portal 本番の実際の実行エンドポイント(DEVPORTAL_SQL_PATH 相当)**と、認証要否(API Key/JWTなど)だけ、提示された時点で dev_portal_client.py の実装が確定します。


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です