「
Groq に相談
」を編集中
2025年7月22日 (火) 22:22時点における
Yuko
(
トーク
|
投稿記録
)
による版
(
差分
)
← 古い版
|
最新版
(
差分
) |
新しい版 →
(
差分
)
ナビゲーションに移動
検索に移動
警告: このページの古い版を編集しています。
公開すると、この版以降になされた変更がすべて失われます。
警告:
ログインしていません。編集を行うと、あなたの IP アドレスが公開されます。
ログイン
または
アカウントを作成
すれば、あなたの編集はその利用者名とともに表示されるほか、さまざまなメリットもあります。
スパム攻撃防止用のチェックです。 決して、ここには、値の入力は
しない
でください!
== 概要 == 生成AIプラットフォームである [https://groq.com GroqCloud] で各種AIを利用するためのMeryマクロです。 ※Llama等のモデルも使えるように適当なタイミングで更新をかけています。 「Google Geminiに相談」マクロでは動作中のストリーム通信に対応するためにV8エンジンで実行していましたが、V8エンジン版は使用上の制限からマクロ実行を開始するまで1秒程度のタイムラグが発生していました。GroqCloudの売りである超高速レスポンスを見込んで本マクロではストリーム通信を使わないようにしました。これにより従来のJScriptで処理を組み立てることができるため、前述のタイムラグが起こらないようになりました。また、ストリーム通信を使わないことで通信量が少なく応答もシンプルになるため、場合によっては「Google Geminiに相談」マクロよりも処理が安定する可能性があります。 【主な機能】 * GroqCloud APIを利用して生成AIと対話できるMery用のマクロ * 選択したテキストやアクティブな行の内容について生成AIに質問・相談が可能 * 会話履歴を保持し、文脈を考慮した対話が可能 【特徴的な機能】 '''会話履歴機能''': * 事前の設定数に応じた会話履歴を保持 * 履歴のクリアが可能 これにより、会話の文脈を考慮した回答を得られます。 '''カスタムインストラクション''': * AIの応答方針を設定可能 * 一時的なカスタム指示の保存と変更が可能 '''プロンプトテンプレート''': * 誤字脱字チェック * 日本語翻訳 * コードの最適化、生成 など、定型的な質問を簡単に実行できます。 ※テンプレート機能では回答を安定させるため、前述の会話履歴を文脈に含みません。 テンプレートは自身の使い方に合わせて好きに追加、削除ができます。詳細はソースコード内の「PROMPT_TEMPLATE」定数のコメントを参照。 == 注意事項 (必ず読んでからご利用ください) == * 本マクロでは 2025/04/13 時点で無料利用ができるGroqCloud APIを利用します。今後、プラットフォームの改定により有償になったり、設定誤り等で費用が発生しても、作者は一切の責任を負いません。 * GroqCloud APIではリクエスト内容をAI学習に用いないことをプライバシポリシーとして謳っているものの、くれぐれも機密情報やプライバシーに関わる情報を指定しないように注意してください。 * GroqCloud APIはプラットフォームの利用規約に則ってご利用ください。 == 利用前提 == * Mery Ver 3.7.13 以上 * GroqCloudで、GroqCloud API APIキーを取得していること (参考 [https://console.groq.com/docs/quickstart Quickstart]) == 利用方法 == * 環境変数の設定 :コマンド プロンプトで以下のコマンドを実行し、環境変数を設定してください。 <syntaxhighlight lang="bat" copy> setx GROQ_API_KEY "***************************************" </syntaxhighlight> :設定後、Mery または Windows の再起動が必要な場合があります。 * マクロの実行 **プロンプトにしたい文字列を選択してマクロを実行すると、選択したテキストがプロンプトとしてGemini APIに送信され、応答がエディタに表示されます。 * 会話の履歴数を調整 ** 会話の履歴は設定した個数分が保持され、文脈として利用されます。適宜、ソースコード内の「HISTORY_SIZE」の数を調整してください。 ** ※数を増やすほど会話内容を保持して文脈を理解するようになりますが、メモリ使用量が増えたり動作が重くなる可能性があります。 ** ※開いている文書ごとに履歴を保持します。文脈をリセットしたいときは、新しい文書を開いて会話をやり直してください。 == ソースコード == <syntaxhighlight lang="javascript" copy> #title = "Groq に相談" BeginUndoGroup(); // カスタムインストラクション // これを設定することで、生成AIの回答全体への生成方針を指示できます。 // 例えば "あなたは「Kimi」という名前のギャルAIアシスタントです。敬語は使いません。絵文字を使って感情表現をします。人懐っこく、バイタリティ溢れる性格で、ユーザーの課題を協力して解決します。" と設定すると、AIの雰囲気が元気な子になります。 // 何も指示しない場合は、空文字 "" を設定してください。 var DEFAULT_CUSTOM_INSTRUCTION = ""; // プロンプトテンプレート // プロンプトテンプレートを設定することで、AIに対して特定の指示を出すことができます。 // プロンプトテンプレートでの生成は会話履歴とカスタムインストラクションを反映しません。 // テンプレートは以下の { ~ }, で囲まれたブロックを好きに増減させて利用できます。 var PROMPT_TEMPLATE = [ // 以下はサンプルです。1階層メニューと2階層メニューが利用できます。 // { // "title": "要約", // "prompt": "以下の文章を要約してください。" // }, // { // "submenu_title": "翻訳系", // "submenu": [ // { // "title": "日本語翻訳", // "prompt": "以下の文章を日本語に翻訳してください。" // }, // { // "title": "英語翻訳", // "prompt": "以下の文章を英語に翻訳してください。" // }, // ] // }, { "submenu_title": "理解を深める", "submenu": [ { "title": "論点を整理する", "prompt": "以下の論点を整理して。" }, { "title": "論理の抜け漏れを探す", "prompt": "以下の論点を整理し、忖度せずに鋭く、論理の抜け漏れを抽出して。そして、そこから発生する可能性のあるリスクも教えて。" }, { "title": "要約する", "prompt": "要約して。専門的な用語と思われる単語は簡単に解説も入れて。" }, { "title": "物語対話形式で教えて", "prompt": "以下の内容について物語対話形式で教えてください。" }, ] }, { "submenu_title": "翻訳する", "submenu": [ { "title": "日本語に翻訳", "prompt": "以下の文章を日本語に翻訳してください。\n" + "出力形式は以下にすること:\n[訳]\n翻訳文...\n" }, { "title": "英語に翻訳", "prompt": "以下の文章を英語に翻訳してください。\n" + "出力形式は以下にすること:\n[Translation]\n翻訳文...\n" }, { "title": "英語->日本語 スラッシュリーディング翻訳", "prompt": "以下の英文を日本語にスラッシュリーディング形式で翻訳してください。\n\n" + "条件:\n" + "- 英文の各フレーズをスラッシュ(/)で区切って表示\n" + "- 各フレーズの日本語訳を括弧()内に併記\n" + "- 文の終わりはダブルスラッシュ(//)で表示\n" + "- 英語の語順に従って日本語訳を行う\n" + "- 日本語訳は自然な日本語である必要はなく、英語の語順を反映した直訳調で構わない\n" + "- 主語が省略されている場合は補って翻訳すること\n" + "- 一般的な英文で頻出する表現がある場合は次の行に記載\n" + "- 以下の出力例のように <英文> (日本語訳) / ... とスラッシュ区切りの繰り返しになる \n\n" + "出力例:\n" + "Snowstorms are forecast (暴風雪が予報されている) / to hit the Sea of Japan coasts (日本海沿岸を襲うと) / of northern to eastern Japan (北部から東部の) / from Sunday through Monday. (日曜から月曜にかけて。) //\n" + "【頻出表現】\n" + "- be forecast to: ~すると予報されている\n" }, ] }, { "submenu_title": "プログラミング支援", "submenu": [ { "title": "コードを洗練させる", "prompt": "以下のコードを洗練させてください" }, { "title": "コードをレビューする", "prompt": "以下のコードをセキュリティと保守性の観点でレビューしてください" }, { "title": "エラーログをデバッグする", "prompt": "以下のエラーログを解析し、考えられる原因と対策を提示してください" }, { "title": "SQLクエリを最適化する", "prompt": "以下のSQL文を最適化してください" }, { "title": "PowerShell スクリプトを書く", "prompt": "以下の処理を行うPowerShellスクリプトを生成してください" }, { "title": "Shell Script を書く", "prompt": "以下の処理を行うShell Scriptを生成してください" }, { "title": "Linux コマンドを提案", "prompt": "あなたはLinuxエキスパートとして、以下のLinuxコマンドを提案してください。\n\n" + "制約条件:\n" + "- 多数のディストリビューションで採用されているメジャーなコマンドを使用し、ポータブルな実装にすること\n" + "- bashでの実行を前提にすること\n" + "- 可能な限りシンプルな実装にすること\n\n" + "期待する出力:\n" + "- コマンドの具体的な実装方法\n" + "- 各コマンドの動作説明\n" + "- 制限事項\n" }, ] }, { "submenu_title": "ビジネス文書作成支援", "submenu": [ { "title": "誤字脱字、不正確な表現をチェック", "prompt": "以下の2つのカテゴリーで問題点を指摘してください\n" + "- 【誤字脱字】:明確な誤字脱字および誤字の疑いがある箇所\n" + "- 【不正確・曖昧な表現】:解釈に個人差が生じる可能性がある表現、より適切な表現に改善できる箇所" }, { "title": "提案書を作成する", "prompt": "以下に対する対する提案書を、コスト・実現性・リスクを含めて作成してください" }, { "title": "仕様書のアウトラインを作成する", "prompt": "以下の内容で仕様書のアウトラインを作成してください" }, { "title": "手順書のアウトラインを作成する", "prompt": "以下の作業を行う手順書を、前提条件と注意事項を含めてアウトラインを作成してください" }, { "title": "ユーザーマニュアルのアウトラインを作成する", "prompt": "以下の機能内容から、ユーザー向けマニュアルのアウトラインを作成してください" }, { "title": "議事録を作成する", "prompt": "以下の会議内容から議事録を作成してください" }, { "title": "進捗報告書を作成する", "prompt": "以下のタスク状況から進捗報告書を作成してください" }, ] }, { "submenu_title": "分析支援", "submenu": [ { "title": "問題を分析し、課題を抽出する", "prompt": "以下の状況から問題や潜在的リスクを分析し、課題を抽出してください" }, { "title": "対応策を提案する", "prompt": "以下の問題・課題に対する対応策を複数提案してください" }, { "title": "傾向を見つける", "prompt": "以下の内容から、数値や挙動上の傾向を見つけてください" }, ] }, { "submenu_title": "アイデア出し", "submenu": [ { "title": "SCAMPER法でブレインストーミング", "prompt": "以下のテーマについて、SCAMPER法を使って15個のアイデアを出してください。制約条件は以下の通りです:" }, { "title": "解決策の幅出し", "prompt": "以下の課題に対して、技術面、運用面、コスト面から実現可能な解決策を5つずつ提案してください" }, { "title": "業務改善案の提案", "prompt": "以下の既存プロセスについて、効率化、コスト削減、品質向上の観点から改善案を提案してください" }, { "title": "逆転の発想", "prompt": "以下の目標に対して、通常とは逆の視点からアプローチする方法を3つ提案してください" }, { "title": "競合分析からの着想", "prompt": "以下の内容について、業界における競合他社の特徴を分析し、差別化できる新しいアプローチを提案してください" }, { "title": "ユースケースの列挙", "prompt": "以下の製品・サービスについて、想定されるユースケースを10個列挙し、それぞれの価値提案を記載してください" }, ] }, ] // 生成AIの回答の言語設定 // "Japanese" や "English" を設定できます。他の言語は未検証。 // 自動設定にする場合は空文字 "" を設定してください。 var LANGUAGE = "Japanese"; // 入力プロンプトの最大トークン数 // 超適当なトークナイザー関数により計測し、英単語は4文字1トークン、それ以外は1文字1トークンとして数えます。 var MAX_PROMPT_TOKEN = 6000; // 会話の履歴を保持する数 (質問と回答で1セット) // 数を増やすと、会話の履歴が増えますが、Meryのメモリ使用量が増えたり、 // 使用トークン数が増えて動作が重くなる可能性があるため、適宜調整してください。 // document.Tag に保持されるため、開いているファイルを閉じると履歴は消えます。 var HISTORY_SIZE = 0; // 会話履歴に保持する最大トークン数 // 会話履歴のトークン数がこの数を超える場合、古い履歴から削除されます。 var MAX_HISTORY_TOKEN = 10000; // コンテキストメニュー番号の定義 var EXECUTE_AI = 1; var RESET_HISTORY = 2; var SET_CUSTOM_INSTRUCTION = 3; var REEXECUTE_LAST_TEMPLATE_PROMPT = 4; var TEMPLATE_PROMPT_THRESHOLD = 10; var TEMPLATE_PROMPT_SUBMENU_THRESHOLD = 1000; // タグ名の定義 var HISTORY_TAG = "groqllama-history"; var TEMPORARY_CUSTOM_INSTRUCTION_TAG = "groqllama-temporary-custom-instruction"; var PREVIOUS_TEMPLATE_PROMPT_TAG = "groqllama-previous-template-prompt"; // 生成AIモデル別設定 // const MODEL_CONFIG = { // model: "meta-llama/llama-4-maverick-17b-128e-instruct", // max_tokens: 3500, // temperature: 0.6, // } // const MODEL_CONFIG = { // model: "qwen/qwen3-32b", // max_tokens: 5000, // temperature: 0.6, // max_completion_tokens: 1024, // reasoning_effort: "default", // reasoning_format: "hidden" // } const MODEL_CONFIG = { model: "moonshotai/kimi-k2-instruct", max_tokens: 5000, temperature: 0.7, } // console.log に出力する内容を Mery のアウトプットバーに表示する var console = { log: function (str) { outputBar.Writeln(str) } } var doc = document; var sel = document.selection; // 生成リクエスト中止フラグ var abortRequestFlg = false // 生成リクエスト完了フラグ; var requestCompletedFlg = false; main(); function main() { var selectionIsEmpty = sel.IsEmpty // プロンプトの取得 if (selectionIsEmpty) { sel.StartOfLine(false, mePosLogical); sel.EndOfLine(true, mePosLogical); } var promptText = sel.Text.trim(); var promptLength = sel.TextLength; var menuTrack = 0; while (true) { // コンテキストメニューの作成 var menu = createContextMenu(selectionIsEmpty); menuTrack = menu.Track(0); // メニュー選択がキャンセルされた場合は終了 if (menuTrack === 0) return; // 会話履歴のリセット if (menuTrack === RESET_HISTORY) { resetTag(); continue; } // カスタムインストラクションの設定 if (menuTrack === SET_CUSTOM_INSTRUCTION) { configureTemporaryCustomInstruction(); return; } break; } // プロンプトが空の場合はエラー if (promptLength === 0) { alert("プロンプトを入力してください。"); return; } // 文字数が多すぎる場合はエラー if (roughTokenize(promptText) > MAX_PROMPT_TOKEN) { alert("プロンプトの文字数が多すぎます。文字数を少なくしてください。"); return; } // 読み取り専用の場合はエラー if (doc.ReadOnly) { alert("ファイルが読み取り専用のため実行できません。"); return; } // 直前に実行したプロンプトテンプレートの再実行の場合、menuTrack を書き換え if (menuTrack === REEXECUTE_LAST_TEMPLATE_PROMPT) { if (doc.Tag.exists(PREVIOUS_TEMPLATE_PROMPT_TAG)) { menuTrack = Number(doc.Tag(PREVIOUS_TEMPLATE_PROMPT_TAG)); } else { alert("直前に実行したプロンプトテンプレートがありません。"); return; } } // テンプレートの場合はプロンプトを変更 var isTemplate = menuTrack >= TEMPLATE_PROMPT_THRESHOLD; var isSubmenu = menuTrack >= TEMPLATE_PROMPT_SUBMENU_THRESHOLD; if (isSubmenu) { var parentMenuTrack = Number(String(menuTrack).slice(0, 2)); var subMenuTrack = Number(String(menuTrack).slice(2)); promptText = "=== INSTRUCTIONS START HERE ===\n\n" + PROMPT_TEMPLATE[parentMenuTrack - TEMPLATE_PROMPT_THRESHOLD].submenu[subMenuTrack].prompt + "\n\n=== INSTRUCTIONS END HERE ===\n\n" + "=== INPUT DATA STARTS HERE ===\n\n" + promptText + "\n\n=== INPUT DATA END HERE ==="; } else if (isTemplate) { promptText = "=== INSTRUCTIONS START HERE ===\n\n" + PROMPT_TEMPLATE[menuTrack - TEMPLATE_PROMPT_THRESHOLD].prompt + "\n\n=== INSTRUCTIONS END HERE ===\n\n" + "=== INPUT DATA STARTS HERE ===\n\n" + promptText + "\n\n=== INPUT DATA END HERE ==="; } // テンプレートの場合は直前に実行したプロンプトテンプレートの番号としてタグに保存 if (isTemplate) { addPreviousTemplatePromptNumberToTag(menuTrack); } try { // 処理終了を待機 shell.KeepRunning = true; // カーソル位置移動 sel.SetActivePoint(mePosLogical, sel.GetBottomPointX(mePosLogical), sel.GetBottomPointY(mePosLogical)); sel.EndOfLine(false, mePosLogical); sel.NewLine(); // APIキーの取得 var apiKey = shell.getEnv("GROQ_API_KEY"); // GroqLlama API に問い合わせ sel.Text = "\n---\n\n" document.KeepScrollPos = true; callGroqLlamaAPI(apiKey, promptText, isTemplate); if (sel.GetActivePointX(mePosLogical) > 2) { sel.Text = "\n\n---\n\n\n" } else { sel.Text = "\n---\n\n\n" } } catch (e) { sel.Text = "<処理中にエラー発生>\n" + e.message + "\n" + e.stack; } finally { // 処理終了待機を解除 shell.KeepRunning = false; } } function createContextMenu(selectionIsEmpty) { var menu = CreatePopupMenu(); menu.Add("※注意※ プライバシー・機密情報を送信しないこと", 0); menu.Add("", 0, meMenuSeparator); var t = ""; if (selectionIsEmpty) { t = "アクティブ行の内容で相談 (&A)"; } else { t = "選択範囲の内容で相談 (&A)"; } menu.Add(t, EXECUTE_AI); if (HISTORY_SIZE <= 0) { menu.Add("├ 会話履歴をクリア (履歴が無効になっています)", RESET_HISTORY, meMenuGrayed); } else if (doc.Tag.exists(HISTORY_TAG)) { var turn = JSON.parse(doc.Tag(HISTORY_TAG)).length / 2; menu.Add("├ 会話履歴をクリア (現在の会話数: " + turn + ") (&C)", RESET_HISTORY); } else { menu.Add("├ 会話履歴をクリア (現在の会話数: 0) (&C)", RESET_HISTORY, meMenuGrayed); } menu.Add("└ カスタムインストラクションを変更 (&I)", SET_CUSTOM_INSTRUCTION); // テンプレート数チェック // 2桁まで許容 var ITEMS_MUX = 99; if (PROMPT_TEMPLATE.length > ITEMS_MUX - TEMPLATE_PROMPT_THRESHOLD) { throw new Error("プロンプトテンプレートの数が多すぎます。"); } // テンプレートの追加 if (PROMPT_TEMPLATE.length > 0) { var subMenu = CreatePopupMenu(); for (var i = 0; i < PROMPT_TEMPLATE.length; i++) { var accelerationKey = ""; if (i === 9) { accelerationKey = " (&0)"; } else if (i < 10) { accelerationKey = " (&" + (i + 1) + ")"; } var menuNum = TEMPLATE_PROMPT_THRESHOLD + i; if (PROMPT_TEMPLATE[i].submenu) { var subMenuList = PROMPT_TEMPLATE[i].submenu; // テンプレート数チェック if (subMenuList.length > ITEMS_MUX) { throw new Error("プロンプトテンプレート (サブメニュー) の数が多すぎます。"); } var subSubMenu = CreatePopupMenu(); var subMenuPrefix = String(menuNum); for (var j = 0; j < subMenuList.length; j++) { var subAccelerationKey = ""; if (j === 9) { subAccelerationKey = " (&0)"; } else if (j < 10) { subAccelerationKey = " (&" + (j + 1) + ")"; } // ES5 compatible version without padStart var subMenuNum = Number(subMenuPrefix + (j < 10 ? "0" + j : String(j))); subSubMenu.Add(subMenuList[j].title + subAccelerationKey, subMenuNum); } subMenu.AddPopup(PROMPT_TEMPLATE[i].submenu_title + accelerationKey, subSubMenu); } else { subMenu.Add(PROMPT_TEMPLATE[i].title + accelerationKey, menuNum); } } if (selectionIsEmpty) { t = "プロンプト テンプレート (対象: アクティブ行) (&T)"; } else { t = "プロンプト テンプレート (対象: 選択範囲) (&T)"; } menu.AddPopup(t, subMenu); t = "└ 直前に実行したプロンプト テンプレートを再実行 (&R)"; if (doc.Tag.exists(PREVIOUS_TEMPLATE_PROMPT_TAG)) { menu.Add(t, REEXECUTE_LAST_TEMPLATE_PROMPT); } else { menu.Add(t, REEXECUTE_LAST_TEMPLATE_PROMPT, meMenuGrayed); } } return menu; } function callGroqLlamaAPI(apiKey, promptText, isTemplate) { try { // fetch で Groq API にリクエスト var requestBody = { messages: createGroqLlamaRequest(promptText, isTemplate), stream: false, }; for (var key in MODEL_CONFIG) { requestBody[key] = MODEL_CONFIG[key]; } if (isTemplate) { // テンプレートの場合は応答を決定論的にする // テンプレート以外の場合はデフォルト値とするために指定しない requestBody.temperature = 0.3; } var url = 'https://api.groq.com/openai/v1/chat/completions'; var http = CreateObject("Msxml2.ServerXMLHTTP"); http.open('POST', url, true); http.setRequestHeader('Content-Type', 'application/json'); http.setRequestHeader('Authorization', 'Bearer ' + apiKey); http.send(JSON.stringify(requestBody)); // 応答待機 var timeout = 60; var retrySec = 0; var startX = sel.GetActivePointX(mePosLogical); var prevPos = sel.GetActivePos(); while (http.readyState != 4) { if (retrySec > timeout) { break; } http.waitForResponse(1); retrySec += 1; inputProgressChar(prevPos); prevPos = sel.GetActivePos(); } // 進捗表示文字を削除 sel.SetActivePoint( mePosLogical, startX, sel.GetActivePointY(mePosLogical), true ); sel.Delete(); // 応答ステータスチェック if (!(http.readyState == 4 && http.status == 200)) { sel.Text = "エラーが発生しました: " + http.status + " " + http.statusText + "\n" + http.responseText; http.abort(); return; } var ret = ""; // JSONをパースして必要なテキストを抽出 var response = JSON.parse(http.responseText); var choices = response.choices; if (choices && choices.length > 0) { choices.forEach(function (choice) { var message = choice.message; if (message) { ret += message.content; } }); } var usage = response.usage; var usageText = ""; if (usage) { usageText += "\n\n(利用トークン数: プロンプト=" + usage.prompt_tokens + ", 応答=" + usage.completion_tokens + ", 合計=" + usage.total_tokens + ")"; } sel.Text = ret + usageText; // 結果を会話履歴に追加 if (HISTORY_SIZE > 0 && !isTemplate) { appendReturnTextToTag(promptText, ret); } } catch (e) { throw e; } finally { requestCompletedFlg = true; } } function roughTokenize(text) { // 超適当なトークナイザ。トークン数をざっくりと多めに数える // 空白文字・ハイフン・アンダースコア区切りの単語に分割して、 // 単語がアルファベットのみ、数字のみの場合には 4文字=1トークン として数える。 // 単語にアルファベット以外の文字が含まれる場合は 1文字=1トークン として数える。 var words = text.split(/[\s\-_]+/); var totalTokens = 0; for (var i = 0; i < words.length; i++) { var word = words[i]; if (!word) continue; // 空の単語をスキップ if (/^[a-zA-Z]+$/.test(word) || /^[0-9]+$/.test(word)) { totalTokens += Math.ceil(word.length / 4); } else { totalTokens += word.length; } } return totalTokens; } // document.Tag の内容を加味してGroqLlamaのリクエストを作成 function createGroqLlamaRequest(promptText, isTemplate) { var customInstructionText = buildCustomInstructionText(); // テンプレートの場合は、会話履歴とカスタムインストラクションを反映しない if (isTemplate) { var request = [ { "role": "user", "content": [{ "type": "text", "text": promptText }] } ]; if (customInstructionText) { request.unshift({ "role": "system", "content": customInstructionText }) } return request; } var tag = document.Tag; // 以前の会話が存在しない場合は新規リクエスト if (!tag.exists(HISTORY_TAG)) { var request = [{ "role": "user", "content": [{ "type": "text", "text": promptText }] }]; if (customInstructionText) { request.unshift({ "role": "system", "content": customInstructionText }) } return request; } // 会話履歴が存在する場合は、履歴を含めてリクエスト var request = JSON.parse(tag(HISTORY_TAG)); if (customInstructionText) { request.unshift({ "role": "system", "content": customInstructionText }); } request.push({ "role": "user", "content": promptText }); return request; } // document.Tag にGroqLlamaの応答を追加 function appendReturnTextToTag(userText, modelText) { var tag = document.Tag; if (!tag.exists(HISTORY_TAG)) { tag(HISTORY_TAG) = JSON.stringify([ { "role": "user", "content": userText }, { "role": "assistant", "content": modelText } ]); } else { var groqllamaText = JSON.parse(tag(HISTORY_TAG)); groqllamaText.push({ "role": "user", "content": userText }); groqllamaText.push({ "role": "assistant", "content": modelText }); // 会話セット (user, model 1往復) が特定セット数を超えた場合、最初のセットを削除 if (groqllamaText.length > HISTORY_SIZE * 2) { groqllamaText.splice(0, 2); } // 会話履歴全体が MAX_HISTORY_TOKEN を超えた場合、最初のセットを削除 var joinedText = ""; for (var i = 0; i < groqllamaText.length; i++) { joinedText += groqllamaText[i].content + "\n"; } while (roughTokenize(joinedText) > MAX_HISTORY_TOKEN) { groqllamaText.splice(0, 2); joinedText = ""; for (var i = 0; i < groqllamaText.length; i++) { joinedText += groqllamaText[i].content + "\n"; } } tag(HISTORY_TAG) = JSON.stringify(groqllamaText); } } function resetTag() { var tag = doc.Tag; if (tag.exists(HISTORY_TAG)) { tag.remove(HISTORY_TAG); } } function baseCustomInstruction() { var language = LANGUAGE.trim(); return "Do not hallucinate. If you are unsure or don't have enough information to answer with confidence, say \"I don't know\" or \"I'm not sure.\"\n" + "If you use Markdown headings (lines beginning with one or more # characters), you must surround the heading with blank lines.\n" + (language ? "Respond in " + language + ".\n" : "") } function buildCustomInstructionText() { var customInstruction = getTemporaryCustomInstruction(); if (!customInstruction) { // 一時的なカスタムインストラクションがない場合はデフォルトを使用 customInstruction = DEFAULT_CUSTOM_INSTRUCTION; } customInstruction = customInstruction.replace(/^[\s ]+|[\s ]+$/g, ""); return (customInstruction ? customInstruction + "\n" : "") + baseCustomInstruction(); } function configureTemporaryCustomInstruction() { var tempCustomInstruction = getTemporaryCustomInstruction(); var prompt = Prompt("カスタムインストラクションを変更 ※変更すると会話履歴がリセットされます", tempCustomInstruction ? tempCustomInstruction : DEFAULT_CUSTOM_INSTRUCTION); if (prompt) { if (prompt === DEFAULT_CUSTOM_INSTRUCTION) { // デフォルトと同じ値の場合はタグを削除 setTemporaryCustomInstruction(""); } else if (prompt !== tempCustomInstruction) { // デフォルト以外の値が設定された場合は保存 setTemporaryCustomInstruction(prompt); } } else { // 空文字でOK、もしくはキャンセルされた場合はデフォルトに戻すか確認 if (Confirm("カスタムインストラクションをデフォルトに戻しますか?")) { setTemporaryCustomInstruction(""); } else { alert("カスタムインストラクションの変更をキャンセルしました。\n※カスタムインストラクションを空にしたい場合はスペースのみを入力してください。"); } } // 変更が加わっている場合は会話履歴をリセット if (tempCustomInstruction !== getTemporaryCustomInstruction()) { resetTag(); } } function getTemporaryCustomInstruction() { var tag = doc.Tag; if (tag.exists(TEMPORARY_CUSTOM_INSTRUCTION_TAG)) { return tag(TEMPORARY_CUSTOM_INSTRUCTION_TAG); } else { return ""; } } function setTemporaryCustomInstruction(temporaryCustomInstruction) { var tag = doc.Tag; if (temporaryCustomInstruction) { tag(TEMPORARY_CUSTOM_INSTRUCTION_TAG) = temporaryCustomInstruction; } else { tag.remove(TEMPORARY_CUSTOM_INSTRUCTION_TAG); } } function addPreviousTemplatePromptNumberToTag(menuTrack) { var tag = doc.Tag; tag(PREVIOUS_TEMPLATE_PROMPT_TAG) = menuTrack; } function inputProgressChar(pos) { sel.SetActivePos(pos); sel.Text = "."; } </syntaxhighlight>
編集内容の要約:
MeryWikiへの投稿はすべて、他の投稿者によって編集、変更、除去される場合があります。 自分が書いたものが他の人に容赦なく編集されるのを望まない場合は、ここに投稿しないでください。
また、投稿するのは、自分で書いたものか、パブリック ドメインまたはそれに類するフリーな資料からの複製であることを約束してください(詳細は
MeryWiki:著作権
を参照)。
著作権保護されている作品は、許諾なしに投稿しないでください!
このページを編集するには、下記の数式を計算してその答えを欄に入力してください (
ヘルプ
):
いちたすには =
キャンセル
編集ヘルプ
(新しいウィンドウで開きます)
スポンサーリンク
ナビゲーション メニュー
個人用ツール
ログインしていません
トーク
投稿記録
アカウント作成
ログイン
名前空間
ページ
議論
日本語
表示
閲覧
編集
履歴表示
その他
検索
スポンサーリンク
スポンサーリンク
案内
メインページ
ヘルプ
よくある質問
マクロリファレンス
マクロライブラリ
プラグインライブラリ
構文ファイル
テーマ
寄付・開発支援
練習用ページ
開発室
開発者のブログ
ツール
スポンサーリンク