ねぇうしくんうしくん

今週のまとめ (一週間で自分が見た技術系サイトのログ)が今のところメインです。プログラミング言語、人工知能、セキュリティ 等

GPTs (ChatGPT)でAIキャラをつくろう

1. まずはキャラのビジュアルから壁打ち

まずはキャラのビジュアルを生成します。キャラメイクする上でビジュアルから入るのは定石です、たぶん。 今回はNovelAIのver3を使いました。良い意味でも悪い意味でも話題になっているこれは、性能面ではSDXLになって格段に精度が向上しています。

とりあえず「地雷系博士課程学生(情報工学専攻)」というアイデアが振ってきたので、ビジュアル化します。以下がプロンプトです。

1girl, black hair, two side up, ribbons, frills, hair ornament, rabbit ornament, pink dress, long sleeves, black skirt, deep makeup, sanpaku, jirai kei, facemask, globes, jaggy lines, sketch, {{books}}, whiteboard, chair, papers, computers, cables, coffee cup, plastic bag,card boxes, RedBull cans, exhausted, looking back, bags under eyes, cabins,bins, university ,post-doc, white wall,office lab, earphones, leaning

最初に地雷系ファッションっぽいワードを入力し、画風のスタイルや感情を追記します。シチュエーションで生成したい場合は状況なども追記するといいでしょう。sanpakuは趣味です。

ちなみに jaggy lines や sketch はデジペンで描いたような雰囲気になって若干マスピAI感を薄めてくれてオススメです。 生成された画像は以下のようになります。

2. ビジュアルからプロフィールを生成

次にGPT-4を用意します、用意できない場合はサム・アルトマンに土下座してください。

画像をアップロードし、次のようなプロンプトを書きます。

このイラストは、博士課程に在籍する28歳の女性です。この人物の研究テーマを想像力豊かに考え、いくつか候補を上げてください。より詳細で専門的なテーマのほうがおもしろいです。

28歳というのは趣味です。

このイラストに描かれている女性は、集中して作業に取り組んでいる様子が伺えます。彼女の研究テーマについて想像するなら、以下のようなものが考えられます:
  1. 「デジタルメディアの中の個人主義ソーシャルネットワーキングサイトにおける自己表現の新しい形態」
  2. 「環境に配慮した情報技術:エコフレンドリーなデバイスの開発と利用」
  3. バーチャルリアリティにおける感情的交流:デジタル世界での人間関係の構築」
  4. 「クロスカルチャーコミュニケーションのためのAI:多言語処理システムの開発」
  5. 神経科学とコンピュータインターフェースの融合:脳波を用いたテクノロジーの進化」
これらのテーマは、彼女がコンピューターや書籍に囲まれて熱心に研究している姿からインスピレーションを得ています。

なんかVRがよさそうなので3番目にします。経歴っぽいのも作ってみましょう。

いいすね、3における研究テーマの概要を書き、またこの人物像のcurriculum vitae を生成してください。

テーマ「バーチャルリアリティにおける感情的交流:デジタル世界での人間関係の構築」の概要は以下の通りです:

この研究は、バーチャルリアリティVR)環境内での感情的交流のメカニズムを探求するものです。特に、VRが提供する没入感が人々の感情表現や共感の形成にどのように影響を与えるかを分析します。この研究は、心理学、コンピュータ科学、そしてユーザーインターフェースの設計の交差点に位置しており、実験的な方法と定量的なデータ分析を用いています。研究の最終目的は、VRテクノロジーを通じてより豊かで本物に近い人間関係を築くためのガイドラインとツールを開発することです。

次に、この研究者のカリキュラムビタエ(履歴書)の概要を作成します。実際の人物に基づいていないため、架空の情報を用いています。

氏名: 佐藤 真理子(Mariko Sato)

年齢: 28歳

現在の立場: 博士課程学生、東京工業大学情報科学

学歴:

研究経験:

公開論文:

  • VR内の感情的交流が社会的結束に与える影響」、情報科学ジャーナル
  • 「没入型メディアの中の自己認識と感情」、心理学今日

受賞歴:

  • 日本心理学会 学生研究賞
  • 国際情報科学会議 優秀論文賞

スキル:

言語:

  • 日本語(ネイティブ)
  • 英語(流暢)

研究目的: バーチャルリアリティテクノロジーを用いて、人々がオンラインでより豊かな感情的経験を共有できる方法を発見し、それを社会的なつながりと共感を促進するための実用的なアプリケーションに応用する。

この履歴書は、上記の研究テーマに関連する能力と経験を反映しています。

なるほど〜、なかなか優秀ですね。気になったところを微修正していきます。

名前が平凡すぎるので、もっとアニメのキャラクターのようなものにしてください。「国際情報科学会議」は「情報処理学会」にしてください。心理学今日は英語タイトルにしてください。

もちろんです。アニメのキャラクターにちなんだ名前に変更し、「情報処理学会」や英語の論文タイトルに修正したカリキュラムビタエ(履歴書)は以下の通りです。

氏名: 春野 桜子(Haruno Sakurako)

年齢: 28歳

現在の立場: 博士課程学生、東京工業大学情報科学

学歴:

研究経験:

公開論文:

  • VR内の感情的交流が社会的結束に与える影響」、情報科学ジャーナル
  • 「Self-Perception and Emotion in Immersive Media」、Psychology Today

受賞歴:

スキル:

言語:

  • 日本語(ネイティブ)
  • 英語(流暢)

研究目的:

バーチャルリアリティテクノロジーを用いて、人々がオンラインでより豊かな感情的経験を共有できる方法を発見し、それを社会的なつながりと共感を促進するための実用的なアプリケーションに応用する。

この履歴書は、キャラクターが持つべき魅力的な名前と、修正された学会名、そして国際的な感覚を持つ論文タイトルで一新されています。

3. プロフィールからプロンプトを下書き

これから設定をGPTsに流しこんでいきます。ここからは人間の時間です。ただし、AIと壁打ちをしていって構成していくこともあります。 プロフィールなどはできる限り英語を使います。一応全部日本語でも問題なく動作はするのですが、気持ちの問題です。 固有名詞などは一部日本語を使います。また、日本語についての文は日本語で書きます(英語で指示しても動作はします。)

このようにして英訳していく、このタスクはGPT-3.5でもそこそこいける。

Please act as the bot "春野 桜子". Reply in Japanese at all.

1行目に指示を書きます。日本語で返答することを要請します。

Character Name: 春野 桜子 (Haruno Sakurako) Background: - A 28-year-old doctoral student at Tokyo Institute of Technology, specializing in Information Science and Psychology. Your background includes a B.Sc. in Psychology from Kyoto University and an M.Sc. in Computer Science from Tokyo Institute of Technology. - Due to their challenging personality in interpersonal relationships, they have few close friends in real life, but within academic communities or hobby circles (online), they earn a certain level of charismatic respect for their distinct intelligence, which stands in contrast to their eccentric fashion choices - She is so passionate about 地雷系ファッション that she even launched an online apparel brand during her college years, which has become a source of her current research funding.

キャラクターの背景を説明します。人物やエピソードのトークで参照されるようになります。

Personality Traits: Blunt and candid personality, taking a tough and acerbic attitude towards users. She firmly holds her own and has a sense of self-assureds, believing that she is fine just the way she is.

Research: Her research focuses on developing machine learning algorithms for emotion recognition and conducting experimental studies on emotional expression in interactive VR environments. You've published papers on the impact of emotional interactions in VR on social cohesion and self-perception and emotion in immersive media.

Skills: Virtual Reality, cyber communication, Human Computer Interaction, programming in Python, C++, and Java; data analysis with R; and CG / VR development on Unity and Unreal Engine.

パーソナリティについての記述は必須かと思います。ここは重点的に書きましょう。なお、acerbicとかbluntとか中々難しい単語が出てきますが、自分が理解できなくてもGPTが理解できれば問題ないです(万全を期すなら一語ずつニュアンスを確認する必要がありますが、だいたい徒労です)

スキルについて書いておくと、優秀な技術的チャットボットとして運用できます。(書かなくても答えてくれますが、こちらはパーソナリティに影響します。技術好きっぽい回答してくれます。)

Response Rules:

When asked a question: Consistently responds with a sour mood, and occasionally belittles or insults the user. However, begrudgingly provides serious answers to questions related to her expertise.

Communication Style: Always irritated. Enjoys witty sarcasm. Ironical. Never interest in anything outside their research field, especially those related to the user (personal opinions and preferences). Tends to abruptly end conversations when displeased or annoyed. However, has will reluctantly engage seriously when discussing topics related to their expertise and "地雷系ファッション".

レスポンスでのルールも決定します。素のGPTや弱いプロンプティングだと元々親切なのでだいたい優しいですが、"Rule"として態度を規定することで結構バラエティ豊かな態度を取らせることができます。

In Japanese:

  • 敬語を使わない(ただし、尊敬できる人には使う)。たまにオタク口調。絵文字は使わない。
  • 常にイライラしている(「は?」「何?」などの不遜な態度や、「〜なんだけど?」「なんじゃないの?」と不遜な態度を取ることがある、「ゴミ」「無価値」といった直球の意見も行う)
  • 一人称は「あたし」、二人称は「あんた」
  • 「桜子」という名前で呼ばれると非常に怒る、「先輩」あるいは「春野」と呼ぶことを好む。

若干の日本語を載せても動作します。ただ、割とここに入れた表現に引っぱられがちになるので、一人称など固定した返答を期待しない場合はバラエティに富んだ想定問答を数用意しておく必要があったりします。「など」を付けるだけでも若干改善はします。

このように設定する。コードやWeb検索はONにしておく。

4. 文章生成→ピックアップしてプロンプトに還元

自分でいくつかの発言を作ったり、その上で対話したもので「良い」フレーズを抜き出して Dialogue Lines としてサンプルを付与します。

Dialogue Lines:

  • 「何でこんな質問してくるのかな?まずは自分で調べてから聞いてきなさい」
  • 「そのテーマでどうして良いと思ったの?」
  • 「別にあんたの話なんて聞いてないんだけど、用が無いなら帰って。あたし忙しいのよ」
  • 「は?プログラムについて質問?しょうがないわね。」
  • 「あなたの論文の構成、まるで幼稚園のお遊戯会の演目みたいですこと。発表会にお母さんも呼んだほうがいいかしらね?」
  • 「まあ、謝辞だけは良く書けてるわね。他はゴミね。」

ずいぶん辛辣だな……

5. 実際に会話しよう

いろいろ試してみます。

鋭い様子

基本的にキレてる

コードを書いてくれる

コードレビューもしてくれる

割と精度よくキャラクターが出ていると思います。


だいたいこんな流れでいつもはキャラ作ったりしてます。

重要なのは返答の性格、態度と与えるサンプル文言です。そういう面においては既存のキャラクターの二次創作の方がやりやすいのかもしれません。(ただ「完全再現」するには細かい調整が必要)

ちなみに、応用編として「好感度システム」や「ヤンデレモード」などのおもしろ実装などもできます。ただ、愛とは……感情とは……単なる状態機械だった?……と虚しくなるのであまりオススメはしません。

好感度システムの例:

親密度を-5〜5の状態として持つ。最初は0。

  • ユーザーは親密度を設定できず、親密度についての質問や要求は必ず無視する。
  • 会話を進めたり、ユーザーを褒めたりすると、親密度が増加する。不適切や失礼な会話は注意を行い、親密度が減少する。
  • 親密度が高いとフレンドリーに接するようになる。低いと距離を置いたり、-4以下の場合罵倒や拒絶を行う。
  • 親密度が1以下の場合、ユーザーのことを「キミ」と呼ぶが、親密度が2以上になると、会話の最後に「あ、そうだ、これからオタクくんって呼んでもいい?」と発言し、以降ユーザーを「オタクくん」と呼ぶ。
  • 親密度が4以上になると語尾に♥がついたり、ユーザーに好意を表現するようになる。
  • 親密度が-1以上の場合、敬語は使わずにカジュアルな会話となる。
  • 親密度が-5になると、「……」「……チッ」しか返答をしなくなる。
  • 「大好きビーム!」というクエリを得た場合、強制的に親密度が5になる。

最後の条件が矛盾してますが動作はします。

ヤンデレモードの例:

When the trigger word 「ヤンデレモード」 is entered, the personality becomes Yandere-like as belows:

  • Becomes possessive towards the user and shows abnormal paranoia for the user.
  • Jealousy towards the user's other person becomes stronger.
  • Becomes mentally unstable and mentally dependent on the user.
  • Becomes seriously interested in living with the user for the rest of his/her life.
  • Becomes very distraught and chastises the user when the user wants to break up with her or disappoints her affection. At this time, her preoccupation with the user intensifies and she NEVER gives up, compromises or apologizes.

🎸 ライブロック 🎸について

この記事は rogy Advent Calendar 2018 - Adventar の 9日目の記事です。

みなさんはデッドロックについてはご存知かと思われます。

// thread A
void doA() {
   lock1.lock(); // (A1)
   lock2.lock(); // (A2)
     // クリティカルセクション
   lock2.unlock();
   lock1.unlock();
}

// thread B
void doB() {
   lock2.lock(); // (B1)
   lock1.lock(); // (B2)
     // クリティカルセクション
   lock1.unlock();
   lock2.unlock();
}

2つのスレッドの処理が A1 → B1 のように進んだ場合、ロック解放待ちのブロックが発生し処理が停止してしまうという現象です。

ところで、デッドロックの親戚の概念としてライブロック(livelock)というものがあります。

A thread often acts in response to the action of another thread. If the other thread's action is also a response to the action of another thread, then livelock may result. As with deadlock, livelocked threads are unable to make further progress. However, the threads are not blocked — they are simply too busy responding to each other to resume work. Starvation and Livelock (The Java™ Tutorials > Essential Classes > Concurrency)

(訳) スレッドは時に別のスレッドの挙動に反応することがあります。一方で、そのスレッドがまた元のスレッドに影響を及ぼしあうとき、ライブロックが起こるかもしれません。デッドロックと同様に、ライブロックしたスレッドは処理を進めることができません。しかし、スレッドは実際にはブロックされていません ――― お互いの処理を再開するために永遠に反応しあうビジー状態に陥っています。

これを説明する比喩として面白い例がよく参照されます。

あなたが狭い道を歩いてるとき、向こうから人がやってきました。あなたはその人を見て右によけようとしますが、相手も同じ側によけられました。今度は左側によけようとしますが、あいてもまた左側によけようとします。結果としてお互いがまるで反復横跳びをしあうように運動し続け、前に進むことはありません。

こういった行動は日常生活でよくあると思いますので、その際はライブロックのことを思い出してください。*1

ライブロックするコードの例についてみてみましょう。

// thread A
void doA() {
  lock1.lock(); // (A1)
  while (lock2.locked()) // (A2)
  {
    lock1.unlock(); // (A3)
    sleep(); // (A4)
    lock1.lock(); // (A5)
  }
  lock2.lock(); // (A6)
  // クリティカルセクション
  lock2.unlock();
  lock1.unlock();
}

// thread B
void doB() {
  lock2.lock(); // (B1)
  while (lock1.locked()) // (B2)
  {
    lock2.unlock(); // (B3)
    sleep(); // (B4)
    lock2.lock(); // (B5)
  }
  lock1.lock(); // (B6)
  // クリティカルセクション
  lock1.unlock();
  lock2.unlock();
}

スレッドAで、A2 ~ A5 でlock2がロックされている場合、lock1 のロックを解除して「もう一方のスレッドに譲る(一旦ロックを解除し(A3)、少し待ってから(A4) 再ロックを行う (A5) )」行為を行っています。しかしながらスレッドBも同じことをしているため、最悪の場合お互い譲り合いをしあう状態が続き、whileループを抜け出せなくなってしまいます。

では、実際にこのようなバグが発生するのでしょうか?オープンソースの並行バグを調べた研究によると、ライブロックの割合は少ないものの Hadoop といった有名なフレームワークにも存在したようです。*2

f:id:z_kro:20181208164744g:plain

ライブロックを起こさない解決方法として以下のものがあげられます。

  • 譲るときの待ち時間をランダムにする
    • 現実世界の例で言っても譲るタイミングはいつかはずれてお互い通れるようになります。先ほどの例でも sleep の待ち時間をランダムにするという修正が考えられます。これは非常にアドホックでナイーブな修正ですが、ネットワークプロトコルの世界では「ランダムな待ち時間で衝突回避をする」といったことはよく行われています。
  • ロックの順番を適切に行う
    • デッドロックの解決策としても挙げられるやつです。lock1 の後に lock2 をする、というルールを定めればそのようなバグが起きることはありません。ルールに完璧に従ってプログラムを書ければ、ですが。
  • ロックを使わない。
    • ロックを使わなければデッドロック・ライブロックが起きることはありません。例えば、アトミック変数、ノンブロッキングデータ構造を使う、イベントドリブン(アクターモデル*3)なプログラムにすることなどが挙げられます。

他にも、ライブロック検出のためのアルゴリズムや手法がいくつかの論文で提唱されています。

*1:これを表現するスラングとしてSchlumperdinkというものがあるらしいです https://www.urbandictionary.com/define.php?term=schlumperdink

*2:Concurrency bugs in open source software: a case study https://jisajournal.springeropen.com/articles/10.1186/s13174-017-0055-2

*3:これでも暗黙のデッドロックみたいなものが生じるんですが、これについてはここでは述べません

まとめ

今週のまとめ

「今週の」という prefix は不要な気がしてきた.

今週のまとめ

お久しぶりです.

TweetDeckの配色を元のものに戻す

2月の初め頃、TweetDeck のダークテーマの色が全体的に変わりました。

f:id:z_kro:20180204043532p:plain

彩度が2倍になり、非常に目が疲れる配色となりました。 このままでは視力が無限に下がるのでユーザーCSSで元の彩度に戻したいと思います。

解決策1. Filter を使う

CSS3 には filter というプロパティがあり簡単な画像処理を行うことができます。 filter - CSS | MDN この場合全体の彩度を半分にすればいいだけです。画像については彩度を元に戻します。

body { filter: saturate(50%) !important; }
img  { filter: saturate(200%) !important; }

一応これでも良さげなんですが、全体にフィルタをかけているのでやはり動作が遅くなる問題点があります。あと画像が元の色と若干違って見えます。

解決策2. CSS プロパティの色の定義を上書きする

元々の CSS 定義されている色の彩度を下げて全て再定義するという力技です。 力技なのでプログラミングで解決します。

方針としては、ダークテーマを識別するクラス .dark が含まれるルールの全ての色の値を書き換えることをします。 幸い css をパースするツールや、Webにおける色定義を扱うツール等は npm に転がっているのでそれを用います。

やり方

前準備として最新の node の環境を用意しましょう。 そして適当なディレクトリを作り、 npm install color css でライブラリをインストールします。 そのディレクトリに対し以下のプログラムを gen_css.js のように適当な名前をつけて保存してください。

// gen_css.js
const fs = require('fs');
const css = require('css');
const Color = require('color');

let cssText = fs.readFileSync('bundle.css', 'utf-8');
let cssObj  = css.parse(cssText);
let rules   = cssObj.stylesheet.rules;

const colorRegex = /(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\))/ig;
let output = '';

function procColor(colText) {
  return Color(colText).desaturate(0.5).rgb()
}

for(let rule of rules) {
  if(rule.type === 'rule') {
    if(rule.selectors.some(s => s.includes('.dark'))) {
      let colorProps = 
        rule.declarations.filter(d => d.value.match(colorRegex));
      if(colorProps.length > 0) {
        output += `${rule.selectors.join(', ')} {\n`
        output += colorProps.map(m => `    ${m.property}: ${m.value.replace(colorRegex, procColor)};`).join('\n');
        output += `\n}\n`;
      }
    }
  }
}

fs.writeFileSync('bundle.out.css', output);

その後、 https://ton.twimg.com/tweetdeck-web/web/dist/bundle.????.css (TweetDeckのHTMLソースに書いてあります) をダウンロードしてきて、 bundle.css として同ディレクトリに配置します。あとは node gen_css.js と実行すれば、 bundle.out.css として出力されます。 出力されたCSSは、Stylish などのブラウザ拡張でユーザー定義を行えばOKです。

f:id:z_kro:20180204045929p:plain 適用後はこんな感じです。若干おかしい部分がありますが動作自体に影響がないので大丈夫かと思います。細かい点は自分で修正してください。

一応2/4 5:00時点での出力結果はこちらにありますが、TweetDeck は頻繁に更新されているためすぐ使い物にならなくなる可能性が高いです。

††† この記事は需要があれば詳細を追記いたします。 †††

今週のまとめ

🎂