자주 묻는 질문각 게시물마다 프롬프트를 커스터마이즈할 수 있나요?
각 게시물마다 프롬프트를 커스터마이즈할 수 있나요?
번역 과정에서 여성 아티스트를 언급하는 기사에 몇 가지 불일치가 발생하고 있습니다. 문제는 동일 인물에 관한 기사임에도 일부 단락에서는 여성형으로, 다른 단락에서는 남성형으로 돌아가버린다는 것입니다.
이는 각 블록을 개별적으로 번역함으로써 전체 맥락이 손실되고, AI가 성별을 판단하지 못할 경우 기본적으로 남성형을 사용하기 때문이라고 생각합니다.
따라서 성별을 일관되게 유지하기 위해 프롬프트에 추가 지침이 필요합니다. 또한 각 게시물마다 선택적으로 이를 적용해야 합니다. 어떻게 하면 될까요?
먼저, 각 게시물을 API에 대한 개별 요청으로 번역하도록 플러그인을 설정해야 합니다.
그런 다음, 번역 중인 게시물 ID를 저장하는 훅을 추가하고, 번역 대상 게시물에 따라 프롬프트를 재정의해야 합니다.
아래 PHP 코드가 그 예시를 보여줍니다:
<?php
// Occurs when a translation process is starting
add_action("gatompl:query_execution_start", "my_gato_query_execution_start", 10, 2);
// Occurs when a translation process is ending
add_action("gatompl:query_execution_end", "my_gato_query_execution_end");
// Customize the prompt
add_filter('gatompl:prompt', "my_gato_custom_prompt", 10, 9);
/**
* The translation process starts here
*
* @param array<string,mixed> $queryVariables
*/
function my_gato_query_execution_start (
string $querySlug,
array $queryVariables
): void {
if ( 'translate-customposts' !== $querySlug ) {
return;
}
/** @var string */
$customPostType = $queryVariables['customPostType'];
if ( 'post' !== $customPostType ) {
return;
}
$a_post_ids = [];
$new_ids = [];
// If customPostId is defined and is an integer
if (isset($queryVariables['customPostId']) && is_int($queryVariables['customPostId'])) {
$new_ids[] = $queryVariables['customPostId'];
}
// If customPostIds is defined and is an array
if (isset($queryVariables['customPostIds']) && is_array($queryVariables['customPostIds'])) {
$new_ids = array_merge($new_ids, $queryVariables['customPostIds']);
}
// Merge without duplicates
if (!empty($new_ids)) {
$a_post_ids = array_unique(array_merge($a_post_ids, $new_ids));
$a_post_ids = array_values($a_post_ids); // Reindexing
}
// Saving the array of post_id of posts currently being translated in the WP options
my_global_store_value('gato-translate-post_ids', $a_post_ids);
}
/**
* The translation process ends here
*/
function my_gato_query_execution_end (string $querySlug): void
{
if ( 'translate-customposts' !== $querySlug ) {
return;
}
// The translations are done, we can empty the stored array of post_id
$a_post_ids = [];
my_global_store_value('gato-translate-post_ids', $a_post_ids);
}
/**
* This is where you define your custom prompt
*
* @param string[] $contents The strings to be translated (eg: `['hello world', 'how are you?']`).
*/
function my_gato_custom_prompt(
string $prompt,
string $providerName,
array $contents,
string $sourceLanguageCode,
string $sourceLanguageName,
string $targetLanguageCode,
string $targetLanguageName,
string $targetCountryCode,
string $targetCountryName
): string {
// Retrieve the array of post IDs for posts currently being translated from the WP options
$a_post_ids = my_global_get_value('gato-translate-post_ids');
if ( !$a_post_ids ) {
$a_post_ids = array();
}
// If we are currently translating only one post, then define a custom prompt
if (empty($a_post_ids) || !is_array($a_post_ids)) {
// Empty or not a valid array
$custom_prompt = "";
} else {
// There is more than one post_id in the array, so we cannot make a more precise prompt
// To avoid this case, go to the plugin settings, "Plugin Configuration" tab, "Translation Option"
// and check "Translate custom posts separately? When translating multiple custom posts at once, enable translating each post separately (in its own request to the API)"
if (count($a_post_ids) > 1) {
$custom_prompt = "";
} else {
// Define your custom prompt here
$custom_prompt = "";
// Add your prompt logic here
//
// Example for translating names into Russian and Asian languages depending on the target language
//
// Russian
if ('ru' === $targetLanguageCode ) {
// Start the custom prompt with 2 line returns (it will be appended to the $prompt at the end)
$custom_prompt .= "\n\nConvert person names to Cyrillic script for the Russian translation. Always translate from a name written in Latin script.";
}
// Japanese
if ('ja' === $targetLanguageCode ) {
// Start the custom prompt with 2 line returns (it will be appended to the $prompt at the end)
$custom_prompt .= "\n\nConvert person names to Japanese with this method : Listen to the original pronunciation of the name, break it into Japanese syllables, write it in katakana.";
}
// Korean
if ('ko' === $targetLanguageCode ) {
// Start the custom prompt with 2 line returns (it will be appended to the $prompt at the end)
$custom_prompt .= "\n\nConvert person names in Hangul, the Korean alphabet, to match the pronunciation.";
}
// Simplified Chinese
if ('zh' === $targetLanguageCode ) {
// Start the custom prompt with 2 line returns (it will be appended to the $prompt at the end)
$custom_prompt .= "\n\nConvert person names by phonetic transliteration using Simplified Chinese characters that match the pronunciation, following Mandarin Pinyin standards. Choose characters with positive or neutral meanings, keep them short (usually 2–3 for given names, 1–2 for family names), and maintain name order unless adapting to Chinese conventions. Do not translate the meaning unless it's a pseudonym or brand with a clear concept. Use existing standard transliterations for well-known names when possible.";
}
}
}
// Add your custom prompt to the initial $prompt and strip off backslashes (while recognizing C-like \n, \r ..., octal and hexadecimal representation)
$prompt = stripcslashes($prompt . $custom_prompt);
// the following line is necessary to really backslash the sentence
$prompt = str_replace('adding a backslash before them (")', 'adding a backslash before them (\")', $prompt);
return $prompt;
}
/**
* Stores an option value in WordPress for global access across all plugins and themes.
* Uses both the options table and, if available, the external object cache (e.g., Redis or Memcached).
*
* @param $my_value An option value to store (mixed). Must be serializable if non-scalar. Expected to not be SQL-escaped.
*/
function my_global_store_value(string $my_key, $my_value): void {
// Save the value in the WordPress options table (persistent across servers).
update_option($my_key, $my_value);
// If an external object cache is active (e.g., Redis, Memcached), store it there too.
if (wp_using_ext_object_cache()) {
wp_cache_set($my_key, $my_value, 'my_cache_group');
}
}
/**
* Retrieves an option value from either the object cache or the options table.
* Ensures the data is available site-wide, even in a multi-server setup.
*
* @return $my_value A value (mixed). Value of the option. A value of any type may be returned, including scalar (string, boolean, float, integer), null, array, object.
*/
function my_global_get_value(string $my_key): mixed {
// First, try to get the data from the external object cache (fastest option).
if (wp_using_ext_object_cache()) {
$my_value = wp_cache_get($my_key, 'my_cache_group');
// If the data was found in cache, return it immediately.
if ($my_value !== false) {
return $my_value;
}
}
// Fallback: read from the WordPress options table (persistent storage).
return get_option($my_key, false); // return false if $my_key does not exist
}