テキストエディタMeryからGoogle Geminiを使うマクロ
相変わらずテキストエディタとしてMeryを使っています。コーディングはVisual Studio Codeをメインに使っていますが、MeryからChatGPTを呼び出すマクロを作って以来、開きっぱなしで使っています。軽量なテキストエディタはいいですね。さて、生成AIの世界もChatGPTのみならず、Gemini、Claudeとたくさんでてきていますが、最近のデータもアクセスできるgemini-2.0-flash-expがよろしそうなので、そちらのマクロも作ってみました。使う方法はChatGPT用マクロと同じで、質問したい内容を選択状態にしておきマクロを実行します。しばらくすると答えが帰ってきます。これもPythonマクロで記述しているのであらかじめ使える環境にする必要があります。また、Geminiを使うための API Keyの取得が必要です。API Keyの値をGOOGLE_API_KEYという名前の環境変数として設定してください。
from google import genai from google.genai import types #model = 'gemini-1.5-flash' #model = 'gemini-1.5-pro' model = 'gemini-2.0-flash-exp' #model = 'gemini-2.0-flash-thinking-exp-1219' # Make messages def make_messages(text): roles = {'assistant': 'model', 'user': 'user'} messages = [] role = 'user' # Initial role content = '' lines = text.splitlines() for line in lines: role_headline = False for key in roles.keys(): if line == f'### {key}': if content: messages.append({"role": roles[role], "parts": [{"text": content}]}) role = key content = '' role_headline = True break if not role_headline: content += line + '\n' if content: messages.append({"role": roles[role], "parts": [{"text": content}]}) return messages if not window.document.selection.Text: window.document.selection.SelectAll() text = window.document.selection.Text messages = make_messages(text) if messages and (messages[-1]["role"] == 'user'): window.document.selection.Text = text client = genai.Client() window.document.selection.Text = '\n\n### assistant\n\n' google_search_tool = types.Tool(google_search = types.GoogleSearch()) chat = client.chats.create( model=model, config=types.GenerateContentConfig( tools=[google_search_tool], response_modalities=['TEXT'], ), history=messages[:-1], ) response = chat.send_message(messages[-1]["parts"][0]["text"]) content = response.text window.document.selection.Text = content # responses = chat.send_message(messages[-1]["content"], stream=True) # for chunk in responses: # content = chunk.text # window.document.selection.Text = content window.document.selection.Text = '\n\n### user\n\n'
MeryマクロをPythonで記述できる様にする方法は次のリンクを参考にしました。 知っておくと便利なテキストエディター「Mery」の 10 個の小技
このマクロを実行するためには Gemini API のキーを入手する必要があります。
見出し
### user
をつけると以下をuser contentとして扱います。見出し
### assistant
をつけると以下をmodel contentとして扱います。
データサイエンスプロジェクトの進行に合わせたファイル名のアルファベット命名法
ファイルをアルファベット順にならべると、データサイエンスプロジェクトの進行順に並ぶようにするための英文字をChat-GPTに考えてもらいもらいました。
user
データサイエンスプロジェクトに含まれるファイル名の先頭につける英字を考えています。機械学習の進行度(探索、データセットの整備、特徴量の選択、モデル構築、プロット、論文化)などがアルファベットの並び(a,b,c,...)と整合させるにはどうすればいいですか。例として考えたものを示します。
- a: ahead advance
- b: basic
- c: clean
- d: dataset
- e: explore
- f: feature
- m: model
- p: print plot publish
- t: test
- x: explore
assistant
データサイエンスプロジェクトの進行度に応じたファイル名の先頭に付ける英字を考えるのは、プロジェクトの整理や進行管理に役立ちます。以下は、アルファベットの並びと進行度を整合させるための提案です。
- a: analysis (初期分析)
- b: basic (基本的な設定や関数)
- c: clean (データクリーニング)
- d: dataset (データセットの準備)
- e: explore (データ探索)
- f: feature (特徴量の選択とエンジニアリング)
- g: generate (データ生成や追加)
- h: hypothesize (仮説の設定)
- i: implement (実装)
- j: join (データの統合)
- k: knowledge (知識の蓄積、参考文献)
- l: learn (学習、モデルの訓練)
- m: model (モデル構築)
- n: normalize (データの正規化)
- o: optimize (最適化)
- p: plot / publish (プロット/論文化)
- q: quality (品質評価、検証)
- r: review (レビューと改良)
- s: summarize (結果の要約)
- t: test (テスト)
- u: update (モデルやデータの更新)
- v: visualize (可視化)
- w: workflow (作業手順)
- x: experiment (実験)
- y: yield (出力、成果物)
- z: z-finalize (最終確認および完了)
このリストは、プロジェクトのニーズや進行状況に応じて調整が可能です。特に、pに関しては「plot(可視化)」と「publish(論文化)」を同時に含めても良いかもしれません。これにより、ファイル名の一貫性と分かりやすさを保ちながらプロジェクトを管理することができます。
Visual Studio CodeからOpen AI ChatGPTを使う拡張機能
以前、テキストエディタのMeryからOpenAI APIをたたくマクロをつくりました。
テキストエディタMeryからOpenAI ChatGPTを使うマクロ - attosci diary
しかし、最近はVSCodeを使うことも多くなりましたので、拡張機能として同様な動作をさせたいと思い、TypeScritバージョンを作りました。環境変数としてOPENAI_API_KEYにOpenAI API Keyを設定する必要があります。
拡張機能の作り方は以下のサイトを参考にしました。使うモデルはコードの中に埋め込んでいるので必要に応じて修正する必要があります。
VSCode Extensions(拡張機能) 自作入門 〜VSCodeにおみくじ機能を追加する〜 #VSCode - Qiita
import * as vscode from 'vscode'; import { OpenAI } from 'openai'; export function activate(context: vscode.ExtensionContext) { console.log('Extension "vscode-openai" is now active!'); const disposable = vscode.commands.registerCommand('vscode-openai.sendToChatGPT', async () => { const editor = vscode.window.activeTextEditor; if (!editor) { vscode.window.showInformationMessage('No active editor!'); return; // No active editor } const document = editor.document; const selection = editor.selection; const text = selection.isEmpty ? document.getText() : document.getText(selection); try { const response = await sendToChatGPT(text); appendTextToDocument(editor, response); } catch (error) { if (error instanceof Error) { // We can now safely read the message property of the Error instance vscode.window.showErrorMessage('Error communicating with OpenAI: ' + error.message); } else { // For other types of thrown values that are not Error instances vscode.window.showErrorMessage('An unknown error occurred.'); } } }); context.subscriptions.push(disposable); } async function sendToChatGPT(text: string): Promise<string> { // Obtain OpenAI API Key from environment variable OPENAI_API_KEY const apiKey = process.env.OPENAI_API_KEY; if (!apiKey) { throw new Error('OpenAI API key is not set in the environment variable OPENAI_API_KEY.'); } const openai = new OpenAI({ apiKey: apiKey }); const model = vscode.workspace.getConfiguration().get('vscode-openai.model', 'gpt-4-turbo'); const messages: any[] = makeMessages(text); const payload = { model: model, messages: messages }; const response = await openai.chat.completions.create(payload); if (response.choices && response.choices.length > 0 && response.choices[0].message.content) { return response.choices[0].message.content; } else { throw new Error('Invalid response from the API.'); } } function appendTextToDocument(editor: vscode.TextEditor, text: string) { editor.edit(editBuilder => { const document = editor.document; let selection = editor.selection; let position: vscode.Position; if (!selection.isEmpty) { position = selection.end; } else { const lastLine = document.lineAt(document.lineCount - 1); position = new vscode.Position(document.lineCount - 1, lastLine.text.length); } const assistantMarker = "\n\n### assistant\n\n"; const userMarker = "\n\n### user\n\n"; const fullText = assistantMarker + text + userMarker; editBuilder.insert(position, fullText); }); } function makeMessages(text: string): any { const lines = text.split('\n'); let messages: any[] = []; const roles: string[] = ['system', 'assistant', 'user']; let current_role: string = 'user'; let content: string = ''; for (const line of lines) { let roleHeadline: boolean = false; for (const role in roles) { if (line.startsWith(`### ${role}`)) { if (content.length > 0) { messages.push({ "role": current_role, "content": content}); } current_role = role; content = ''; roleHeadline = true; break; } } if (!roleHeadline) { content += line + '\n'; } } if (content.length > 0) { messages.push({ "role": current_role, "content": content}); } return messages; } export function deactivate() {}
テキストエディタMeryからOpenAI ChatGPTを使うマクロ
ここ数年はテキストエディタとしてMeryを使っています。最近はVisual Studio Codeをコーディングに使う事がめっきり多くなりましたが、軽量なテキストエディタはなかなか手放せません。さて、最近流行りのChatGPTですが、これをエディタの中で使うと便利ではないかと思い立ちMeryのマクロを作ってみました。質問したい内容を選択状態にしておきマクロを実行します。しばらくすると答えが帰ってきます。Pythonマクロなので若干の設定が必要なことと、OpenAI API Keyの取得が必要です。OpenAI API Keyの値をOPENAI_API_KEYという名前の環境変数として設定してください。
from openai import OpenAI # import json def make_messages(text): roles = ['system', 'assistant', 'user'] messages = [] role = 'user' content = '' lines = text.splitlines() for line in lines: role_headline = False for key in roles: if line == f'### {key}': if content: messages.append({"role": role, "content": content}) role = key content = '' role_headline = True break if not role_headline: content += line + '\n' if content: messages.append({"role": role, "content": content}) return messages client = OpenAI() if not window.document.selection.Text: window.document.selection.SelectAll() text = window.document.selection.Text messages = make_messages(text) # window.alert(json.dumps(messages)) if messages: response = client.chat.completions.create(model="gpt-4-turbo", messages=messages) content = response.choices[0].message.content.lstrip() window.document.selection.Text = text + '\n\n### assistant\n\n' + content + '\n\n### user\n\n'
MeryマクロをPythonで記述できる様にする方法は次のリンクを参考にしました。 知っておくと便利なテキストエディター「Mery」の 10 個の小技
このマクロを実行するためには OpenAI API のキーを入手する必要があります。
見出し
### system
をつけると以下をsystem contentとして扱います。見出し
### user
をつけると以下をuser contentとして扱います。見出し
### assistant
をつけると以下をassistant contentとして扱います。
ユピテルY-300dPの画像から加速度データを得る
最近、ドライブレコーダーを買いました。 ユピテル Yupiteru のY-300dPです。 発売は2021年と少々古いのですが、性能が良く値段が手頃なので気に入っています。 このドラレコは衝突や急ブレーキ、急ハンドルなどで異常な加速度を検知した場合、 前後40秒のデータを別フォルダに格納する機能がついています。 その際に加速度の閾値を適切に決めないと頻繁にアラーム音とともに動作してしまうので 設定を調整する必要があります。 画像をPCで確認するプログラムとのことで、 調べてみると字幕データとしてフレームごとに記録されているようです。 というわけでPythonコードを書いてみました。
# AVI Audio Video Interface # RIFF Resource Interchange File Format import struct # # Read RIFF Header # def read_RIFF_header(f): buffer = f.read(12) riff, size, type = struct.unpack('<4sI4s', buffer) if riff != b'RIFF' or type != b'AVI ': raise ValueError('Not a valid AVI file') return size def read_list(f, read_data=True): buffer = f.read(12) id, size, type = struct.unpack('<4sI4s', buffer) if id != b'LIST': raise ValueError('Not LIST.') if read_data: buffer = f.read(size - 4) if size % 2 == 1: f.read(1) # Read one more byte if size is odd. return size, type, buffer return size, type def read_chunk(f, read_data=True): buffer = f.read(8) id, size = struct.unpack('<4sI', buffer) if read_data: buffer = f.read(size) if size % 2 == 1: f.read(1) # Read one more byte if the size is odd. return id, size, buffer return id, size file = '~~~.avi' f = open(file, 'rb') # # Check RIFF Header # size = read_RIFF_header(f) size, type = read_list(f, read_data=False) if type != b'hdrl': raise ValueError('list_type is not hdrl.') # # Main AVI Header # id, size, buffer = read_chunk(f) if id != b'avih': raise ValueError('chunk_type is not avih.') # # Stream Header Lists # fccType = 'vids', 'auds', 'txts' # for i in range(3): size, type, buffer = read_list(f) if type != b'strl': raise ValueError('list_type is not strl.') # # JUNK Chunks # for i in range(2): id, size, buffer = read_chunk(f) if id != b'JUNK': raise ValueError('chunk_type is not JUNK.') # # movi List # movi_size, type = read_list(f, read_data=False) if type != b'movi': raise ValueError('listtype is not movi.') current_size = 0 ax_list = [] ay_list = [] az_list = [] while current_size < movi_size: id, size, buffer = read_chunk(f) if id == b'02tx': f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, \ ax, ay, az, n, speed, latitude, longitude, unix_time = struct.unpack('<13fI3fI', buffer) ax_list.append(ax) ay_list.append(ay) az_list.append(az) print(ax, ay, az, n, speed, latitude, longitude, unix_time) current_size += size f.close()
私が購入したドラレコの型番はY-300dpなのですが、 LaBoon!!さんのサイトでは、 同様なハードが様々な型番(WDT700c, SN-TW9900d, SN-TW9800d, Y-300C, Y-300R, Y-210R, SN-TW99c, SN-TW84d)で販売されているとの事で、 ひょっとしたらこれらのドラレコでもデータが抽出できるかもしれません。