オーディオテクニカから、ウェブ会議などで使うスピーカーフォン新モデル「AT-CSP7」が発売される。「ウェブ会議ならイヤホンでも事足りるのでは」と思いつつも、実際に使ってみたら思いの外……というより非常に便利だったので、その魅力をレビュー記事としてレポートしたい。
Source link
Views: 0
オーディオテクニカから、ウェブ会議などで使うスピーカーフォン新モデル「AT-CSP7」が発売される。「ウェブ会議ならイヤホンでも事足りるのでは」と思いつつも、実際に使ってみたら思いの外……というより非常に便利だったので、その魅力をレビュー記事としてレポートしたい。
Source link
Views: 0
今回のやること
今回の目標はUnityのインスペクター上でDictionary型を編集できるようにします。
最終的な見た目は以下のようになります。
今回のゴール
Dictionary型はキーとバリューの2つの変数の型を指定します。この部分は自分で好きな型を指定できるような汎用性の良いプログラムで作成していきます。
開発環境
Unity6
VisualStudio2022
制作
今回作成したソースコードは以下のようになります。そこまで、難しいくはないと思います。
SerializeDictionary
using UnityEngine;
using System.Co…
Source link
Views: 0
ジュリア・エヴァンスは非常に関連性があり、非常に魅力的な話をしています 難しいものを簡単にする。ジュリアには、難しいことで有名であり、理解しやすくするテクノロジーの概念に指を置く方法があります。彼女は、削減されたオプションやコマンドのセットを学ぶなど、自分の戦術を共有することによって、そして 非常に親しみやすいガイドを作成します。
私は彼女の式が好きです: まれな使用 +たくさんのゴッチャス=災害。
(CSSの男として、人々がCSSについて不平を言うのを定期的に聞く人として、これはトラックです。)
その災害を避けるためのもう1つのトリックは、コンピューターを使用することです! Linterなどのツールは、テクノロジーをイライラさせたりエラーが発生したりする可能性のある間違いを修正(または回避する)のに役立ちます。彼女はツールを使用しています シェルチェック、Bashスクリプトの問題を回避するための例として、私はこれを聞いたことがありませんでした。それから、 共有 このようなツールを見つけたら 実際にあなたを助けてください。 その最後のビットは特に興味深いものでした。本当にあなたを助けたツールを共有することについて「知的に正直」であることは良いことです。 思われる 彼らのように できた 彼らは見栄えが良いので、あなたを助けてください。
難しいことといえば…あなたは何が難しいのか知っていますか?リファクタリング。私はおそらくこれを過剰に繰り返しましたが、David Khorshidは、「レガシーコードではなく伝説的なコードと呼ばれるべきだ」と言いました。これは、生産中のコードが仕事をしているコードは、たとえそれがずさんで、非効率的で、不可解で、文字通り必要な仕事をしていると思われます。一方、理論的に書き直されたいくつかの素晴らしいコードは、まだそれ自体を証明していません。
コードリファクタリングは、正しく行われないと大金がかかる場合があります。機能不全の改良システムまたは新機能と誤った書き換えと相まって、間違いなく損害を与えます。どんな程度まで議論することができます。
リファクタリングコードは非常に危険な場合があるため、自分がしていることについて非常に思いやりを持つ価値があります。ミロスラフのポイントのいくつか:
fhater機能からの改善を分離します。 同時に適用しないでください。
conge高価なクリーンアップと他の変更を混ぜないでください。 しかし、わずかな改善のためにそれを行います。
これにより、TypeScriptについて考えさせられます。
TypeScriptは(ええと、明らかに)JavaScriptよりも新しいので、かなりの量のコードがあります。 修正 TypeScriptに。それよりも価値があるかどうかは議論の余地があります。それを愛する人々は、このようなリファクタルが実際にコードを作ると言うかもしれません より安全、そして、おそらくある程度は間違っていませんが、リファクタリングされたコードにリスクがあると主張するのは難しくありません。
タイプスクリプト自体にもコストがあります。もちろん、ツールなどを構築するだけでなく、構文自体も構築します。レミー・シャープはそれを呼びました 彼自身の個人的なコードはタイプスクリプトではありません、部分的にこのため:
「よく作成された」定義、タイプ、またはインターフェイス(それぞれをいつ使用する必要があるかはまだわかりません)は、多くの場合、私にとって大きな認知負荷です。
たくさんの二重コロンが提示されている、
何がわからないとき
T
指を指します。インターフェイスの壁などは、私、読者にとって前払いコストです。多くの場合、タイプは他のファイルに隠されます(おそらく良い)が、関数呼び出しに必要な引数を解決することは、しばしば私の関数呼び出しを行うのではなく、必要なものを理解するタスクに気を取られます。
私はそれを感じます。 Codepenでは、できる限り利用することにしたので、私はゆっくりとタイプスクリプトが上手になっています。私はその価値をかなり定期的に見ることができますが、私はそれによってかなり定期的にイライラしており、失われた時間に疑問を投げかけています。私は何年もこのように感じましたが、それをどうするべきかはまだよくわかりません。
何かをリファクタリングする理由の1つは、いくつかの新しい抽象化を決めたからです。私の経験では、クラシックは、フレームワークを追加、ドロップ、または変更することです。古いものはもうそれをしていません。おそらく、十分に大きなコードベースが常に10万行以上のコードあたり少なくとも1つのリファクタリングを受けているある種の公理があります。
読んだことがありますか ハンマー工場のもの?それはかなり満足のいく読み物であり、コメディでのいくつかの時代遅れの刺し傷を除いて、かなり女性嫌悪的に読んでいます。時々あなたはハンマーを必要とするだけで、それは明らかに仕事に適したツールですが、業界はあなたにオールインワンのハンマー、待って、いいえ、ハンマー工場、待って、いいえ、ハンマー工場を建設するための工場、待って、いいえ…
フロントエンドの特定の作業は、常にバックエンドの作業よりも価値の低いものとして扱われていることは私には当てはまります。私を憎まないでください、しかし、私の一部はそれが公平だと感じています。私は自分自身がフロントエンドの男であり、実際には非常に価値があると思いますが、最終的にほとんどの製品は、ある種のユニークなバックエンドの魔法にあります。全体として、バックエンドの問題はより硬く、よりリスクがあり、怖いものであり、それはより高い支払いの役割につながります。もちろん、ここにはたくさんのニュアンスがあります。非常にまともなバックエンドとトータルゴミのフロントエンドを備えた製品は、実際に物事を使用している人々の経験が悪いため、人々が愛する経験を作るために完全に失敗する可能性があり、フロントエンドに向かって重み付けされています。 またはジョシュ・コリンズワースが最近書いたように:
多くの点で、CSSは、ユーザーのエクスペリエンスに他のどの言語よりも大きな影響を与えます。これは、成功に直接影響することがよくあります。では、なぜその役割はそんなに軽視されているのでしょうか?
以前は、フロントエンドとバックエンドの両方を知っていたら、 ユニコーン そして、それは非常にまれであると考えられており、あなたはこの業界で強力な力でした。今、ユニコーンは死んでいます。私たちは今それを「フルスタック」と呼びますが、それはあなたが1つであると予想されています。 特に あなたがフロントエンドに熟練しているなら、あなたはそれをただ言うことはできません、あなたは「フルスタック」またはあなたの仕事の見通しが見栄えが良くないと言わなければなりません。フルスタックの実際の期待は、あなたがJavaScriptのものが得意であることを意味します。あなたは、JavaScriptクライアントがサーバー上のJavaScriptと動作することをつなぐ作業に問題があり、デザインシステム、ライブラリ、またはいくつかの実行可能なものを使用するのに十分なフロントエンドを知っています。
とにかく、それはただの考えです。それは私の心の中で固まりました アンドリュー・ウォルポールを読む:
フルスタック開発者が生まれました!
特に給与部門にとっては、紙の上で見栄えがよくなります。伝統的に2つの役割を果たす人が1人です。しかし、実際には、私たちはそれがそのように機能しないことを知っています。テクノロジージェネラリストが成功する役割かもしれませんが、1人の人の努力は有限であり、一貫した製品開発スペクトル全体にわたって、焦点と専門知識が必要です。それにもかかわらず、新興企業は効率を高め、Web技術の激動の解約ではまともな防御でした。
がある 新しいnode.js Webサイト そして、それはいつも楽しいです 少し舞台裏を読んでください。それは大変な仕事になるでしょうが、彼らは素晴らしい仕事をしたようです。
Views: 0
AIエージェントで多いユースケースにPC操作やブラウザ操作があります。
最近はMCPが盛り上がっており、Playwright-MCPのようなMCPに対応したサーバを利用してエージェントを作成・実行することも多いと思います。
とはいえ、従来のFunction/Tool Callingからブラウザ操作するエージェントもこれはこれで使い勝手が良いと考えています。
というわけで時機を外した感はありますが、Databricksのカスタムエージェントとしてブラウザ操作するエージェントを軽く作ってみたい欲求にかられましたので作成してみます。
また、Mosaic AI Model Serving上にエージェントをデプロイします。
開発はDatabricks on AWS上で行いました。
ノートブックのクラスタはサバ―レスではなく、アクセスモード=専用のクラスタを利用してください。(Playwrightの依存パッケージがインストールできないため)
必要なパッケージをインストールします。
今回、ブラウザ操作は以下のbrowser-use
で行いました。browser-use
をラップしてエージェントを実装した形となります。
%pip install -U -qqqq databricks-langchain databricks-agents>=0.16.0 mlflow-skinny[databricks] langgraph==0.3.21 uv loguru rich browser-use nest-asyncio
%restart_python
MLflow ChatAgentインターフェースを実装したクラスを定義します。
browser-useのエージェントを内部で実行し、結果をChatAgentResponse
クラスに変換して返しています。
LLMはClaude 3.7 Sonnetを利用しました。
%%writefile browser_use_agent.py
from typing import Literal, Generator, List, Optional, Any, Dict, Mapping, Union
import uuid
import mlflow
from databricks_langchain import (
ChatDatabricks,
)
from langgraph.func import entrypoint, task
from databricks_langchain import ChatDatabricks
from mlflow.pyfunc import ChatAgent
from mlflow.types.agent import (
ChatAgentMessage,
ChatAgentResponse,
ChatContext,
ChatAgentChunk,
)
import subprocess
import asyncio
from browser_use import Agent, Browser, BrowserConfig
from playwright._impl._driver import compute_driver_executable, get_driver_env
# mlflow tracing
mlflow.langchain.autolog()
def install_playwright():
"""Playwrightの依存関係をインストールします。"""
driver_executable, driver_cli = compute_driver_executable()
args = [driver_executable, driver_cli, "install", "--with-deps"]
proc = subprocess.run(
args, env=get_driver_env(), capture_output=True, text=True, check=True
)
return proc == 0
@task
async def call_browser_use_agent(llm, task: str):
"""ブラウザを使用してタスクを実行します。"""
config = BrowserConfig(headless=True, disable_security=True)
browser = Browser(config=config)
agent = Agent(
task=task,
llm=llm,
browser=browser,
)
results = await agent.run()
await browser.close()
return results
@entrypoint()
async def workflow(inputs: dict) -> dict:
"""ブラウザ操作を行うLangGraphのグラフを構築"""
message = inputs.get("messages", [{}])[-1]
llm = inputs.get("llm")
return call_browser_use_agent(llm, message.get("content", None))
class BrowserUseChatAgent(ChatAgent):
def __init__(self, llm):
"""LangGraphのグラフを指定して初期化"""
self.llm = llm
def predict(
self,
messages: list[ChatAgentMessage],
context: Optional[ChatContext] = None,
custom_inputs: Optional[dict[str, Any]] = None,
) -> ChatAgentResponse:
"""
指定されたチャットメッセージリストを使用して回答を生成する
Args:
messages (list[ChatAgentMessage]): チャットエージェントメッセージのリスト。
context (Optional[ChatContext]): オプションのチャットコンテキスト。
custom_inputs (Optional[dict[str, Any]]): カスタム入力のオプション辞書。
Returns:
ChatAgentResponse: 予測結果を含むChatAgentResponseオブジェクト。
"""
request = {
"messages": self._convert_messages_to_dict(messages),
"llm": self.llm,
}
results = asyncio.run(workflow.ainvoke(request)).result()
messages = [
ChatAgentMessage(
id=str(uuid.uuid4()),
role="assistant",
content=h.result[-1].extracted_content,
attachments={
"url": h.state.url,
"title": h.state.title,
"screenshot": h.state.screenshot,
},
)
for h in results.history
]
usage = {
"prompt_tokens": results.total_input_tokens(),
"completion_tokens": None,
"total_tokens": results.total_input_tokens(),
}
return ChatAgentResponse(
messages=messages,
usage=usage,
)
def predict_stream(
self,
messages: list[ChatAgentMessage],
context: Optional[ChatContext] = None,
custom_inputs: Optional[dict[str, Any]] = None,
) -> Generator[ChatAgentChunk, None, None]:
"""
指定されたチャットメッセージリストを使用して、非同期的にエージェントを呼び出し、結果を取得します。
Args:
messages (list[ChatAgentMessage]): チャットエージェントメッセージのリスト。
context (Optional[ChatContext]): オプションのチャットコンテキスト。
custom_inputs (Optional[dict[str, Any]]): カスタム入力のオプション辞書。
Returns:
ChatAgentResponse: 予測結果を含むChatAgentResponseオブジェクト。
"""
request = {
"messages": self._convert_messages_to_dict(messages),
"llm": self.llm,
}
results = asyncio.run(workflow.ainvoke(request)).result()
for h in results.history:
delta = ChatAgentMessage(
id=str(uuid.uuid4()),
role="assistant",
content=h.result[-1].extracted_content,
attachments={
"url": h.state.url,
"title": h.state.title,
"screenshot": h.state.screenshot,
},
)
yield ChatAgentChunk(
delta=delta,
usage={
"prompt_tokens": h.metadata.input_tokens,
"completion_tokens": None,
"total_tokens": h.metadata.input_tokens,
},
)
# PlaywrightをInstall
install_playwright()
# DatabricksネイティブのClaude 3.7 SonnetをLLMとして利用
LLM_ENDPOINT_NAME = "databricks-claude-3-7-sonnet"
llm = ChatDatabricks(model=LLM_ENDPOINT_NAME)
AGENT = BrowserUseChatAgent(llm)
mlflow.models.set_model(AGENT)
作成したエージェントをmlflowでロギングします。
import mlflow
from browser_use_agent import LLM_ENDPOINT_NAME
from mlflow.models.resources import DatabricksServingEndpoint
from rich import print
resources = [DatabricksServingEndpoint(endpoint_name=LLM_ENDPOINT_NAME)]
input_example = {
"messages": [
{
"role": "user",
"content": "日経平均株価はいくら?"
}
]
}
print(input_example)
with mlflow.start_run():
logged_agent_info = mlflow.pyfunc.log_model(
artifact_path="agent",
python_model="browser_use_agent.py",
input_example=input_example,
pip_requirements=[
"mlflow",
"langgraph==0.3.21",
"databricks-langchain==0.4.1",
"browser-use==0.1.40",
],
resources=resources,
)
ロギングしたモデルを利用して推論してみます。
run_id = logged_agent_info.run_id
mlflow.models.predict(
model_uri=f"runs:/{run_id}/agent",
input_data={"messages": [{"role": "user", "content": "Hello!"}]},
env_manager="uv",
)
出力結果
INFO [agent] 🚀 Starting task: Hello!
INFO [agent] 📍 Step 1
INFO [agent] 🤷 Eval: Unknown - This is the first step of the task. I am starting with a blank page.
INFO [agent] 🧠 Memory: I am starting with a blank page. The ultimate task is to say 'Hello!'. This is a simple greeting task that I can complete immediately.
INFO [agent] 🎯 Next goal: Complete the task by saying Hello!
INFO [agent] 🛠️ Action 1/1: {"done":{"text":"Hello!","success":true}}
INFO [agent] 📄 Result: Hello!
INFO [agent] ✅ Task completed
INFO [agent] ✅ Successfully
{"messages": [{"role": "assistant", "content": "Hello!", "id": "89fc1657-3744-42c2-8b36-2b66fdb59921", "attachments": {"url": "about:blank", "title": "", "screenshot":(省略)
ブラウザ操作はおこなっていませんが、問題なく動作はしていそうです。
では、Mosaic AI Model Serving上にエージェントをデプロイしてみましょう。
まず、Step1でロギングしたエージェントをUnity Catalog上に登録します。
import mlflow
mlflow.set_registry_uri("databricks-uc")
catalog = "training"
schema = "llm"
model_name = "browser_use_agent"
UC_MODEL_NAME = f"{catalog}.{schema}.{model_name}"
# Unity Catalogへの登録
uc_registered_model_info = mlflow.register_model(
model_uri=f"runs:/{run_id}/agent", name=UC_MODEL_NAME
)
次にMosaic AI Agent Frameworkを使ってMosaic AI Model Servingへデプロイします。
from databricks import agents
agents.deploy(
model_name=UC_MODEL_NAME,
model_version=uc_registered_model_info.version,
scale_to_zero=True,
)
問題なければ数分程度でデプロイが完了します。
たまにPlaywrightの依存関係インストールに失敗することがありました。
うまくいかない場合はデプロイをやり直してください。
では、デプロイしたエージェントを試しに使ってみます。
今回はDatabricksのPlayground上でエージェントに指示を出してみました。
まず、「日経平均株価を教えて」もらいます。
操作している画面は表示されませんが、Googleで検索して情報を取得してくれました。
検索系ばかりですが、もう1個ぐらい指示してみます。
Bリーグ公式サイトの中まで入って情報を取って来てくれていますね。
なお、デプロイしたエージェントは、ブラウザ操作画面のスクリーンショットも出力するようにしていますので、それを利用してブラウザ操作画面履歴を出したりといったこともできるようにしています。(通信量が増えてしまっていますが)
習作として、ブラウザ操作エージェントをDatabricks上で作成&デプロイしてみました。
作りが甘く実用性はまだまだです。特に結果を全てassistantとして返したり、ストリーミング処理が適当だったりは改善の余地が大きい。
とはいえ、ちょっとしたブラウザ処理の自動化には利用できるかなと思います。
(個人的にはマルチエージェントシステム内のひとつのエージェントとして使えればと考えています)
次はMCPに対応したエージェントも作ってみたいなあ。
Views: 0
東京ディズニーランドは4月7日、パーク内に登場する「BDXドロイド」を初公開した。
「BDXドロイド」は、2足歩行で移動する小型のロボット。「STAR WARS ジェダイ:フォールン・オーダー」で初登場する「BD-1」と同型式のコンパニオン・ドロイドとなる。登場したのは3体で、名前はオリー(オレンジ)、グリン(グリーン)、ビーボー(ブルー)。
4月7日は「BDXドロイド」がトゥモローランドエリアに登場し、ゲストへのグリーティングを実施。3体の「BDXドロイド」はテクテクと歩行しながら、ときに立ち止まって周囲をスキャンしたり、周りに顔を向けたりしながら、ゲストたちとコミュニケーションしていった。
【東京ディズニーランド スター・ウォーズ「BDXドロイド」お披露目】
Views: 0
Virtual Sky Interactiveは、アドベンチャーゲーム『Cafe New York 9/11』を開発中だ。発売日は未定。対象プラットフォームはPC(Steam)。
本作は、2001年9月11日朝のマンハッタンを舞台にした物語主導のアドベンチャーゲーム。プレイヤーはカフェのオーナーとなり、世界が変わる大事件に遭遇する。
パキスタン系アメリカ人「サミール」は、ニューヨーク市のロウアー・マンハッタンに店舗を構えるカフェのオーナーをしていた。2001年9月11日の朝、いつものように常連客がコーヒーと朝食を求めて訪れ、ヤンキースの試合や仕事の会議、週末の予定について会話をしている。
しかし外では大事件が起こり、すべてが一変する。世界が混乱に陥るなか、怯える見知らぬ人々、常連客によって、スタッフが集まり、カフェは一時的な避難所となる。プレイヤーはオーナーの「サミール」の視点から、この信じがたい朝の出来事を体験する。
本作は、世界を震撼させた「アメリカ同時多発テロ事件」を題材にしつつ、カフェを経営する移民の視点から、人々がパニックに陥り、家族や友人と連絡を取ろうとし、避難先を求める様子を目の当たりにする。
カフェのざわめき、遠くのサイレンの音、本格的なパキスタン音楽が流れつつ、人種差別、家族、コミュニティ、希望、回復力といったテーマを通して、プレイヤーは逆境の中で築かれた人間関係を強調した心温まるストーリーが展開するという。
Working an all nighter on the final cut of the teaser trailer for Cafe New York 9/11 and got a little emotional. Feels surreal to be able to see Pakistani culture, music, characters, and more in a game and more importantly, in a positive light, which is one of the things I want… pic.twitter.com/qIJqiXo1Bs
— Baqir Shah 🇵🇰🇾🇪 (@bakershah) April 5, 2025
本作を開発しているBaqir Shah氏は、『ライフ イズ ストレンジ ダブルエクスポージャー』のリードレベルデザイナーなどの開発経験がある人物。
同氏のXアカウントのポストによると、現在、本作のティザートレーラーに徹夜で取り組んでいるとのこと。記事執筆時点では映像が公開されていないが、お披露目する時期も近そうだ。
「アメリカ同時多発テロ事件」を、パキスタン系アメリカ人が経営するカフェから体験するアドベンチャーゲーム『Cafe New York 9/11』は、Steam向けに発売予定だ。
本ページはアフィリエイトプログラムによる収益を得ている場合がございます
Views: 0