APIで呼んでいるQwenに、天気とニュースを調べて答えさせた
目次
StackChanを音声チャットにつないだ記事の最後で「今の天気は。」と聞いたときは、外の様子はわからないと返された。
このころの音声チャットサーバーは、ModelScopeのAPIでQwenを呼んでいるだけで、調べものをする仕組みは入れていなかった。
10月20日の0時過ぎ、フォトフレームにしたXperiaのタブレットから同じサーバーに「今日の東京の天気は。」と聞くと、やはり「ごめん、今日の東京の天気はわからないんだよね。」と返ってきた。
ところがこのサーバーは、Qwenを呼ぶときにModelScopeの内蔵のWeb検索を有効にする enable_search: True を付けている。検索を付けているのに、なぜ天気がわからないのかを調べた。
調査と変更は、音声チャットサーバーのPCで動いているClaudeに頼んで進めてもらった。この記事の数字はその報告と、一緒に送られてきた試験スクリプトの出力から取っている。
音声チャットサーバーの構成
| 部分 | 中身 |
|---|---|
| 文字起こし | Qwen3-ASR-0.6B(サーバーのGPUで動かす) |
| 返事を作るLLM | Qwen3.8-Max(ModelScopeのAPI-Inference経由) |
| 読み上げ | 別のTTSサーバー(文章から音声を作る) |
| 話し相手 | StackChan、Xperiaのタブレット |
返事は「かな」というキャラクターの話し言葉で、読み上げるので2文以内にしている。
LLMに最初に渡す指示(システムプロンプト)には、現在の日時、StackChanが測ったCO₂・温度・湿度、長期記憶から探した記憶を入れている。
検索は動いていた
まず、内蔵の検索が本当に動いているかを確かめた。
日時だけを書いた短いシステムプロンプトで、enable_search の有無だけを変えて同じ質問を送り、APIの応答に入っている入力のトークン数を比べた。入力のトークン数はLLMに渡した文章の長さを表す。
| 質問 | 検索ありの入力トークン数 | 検索なしの入力トークン数 |
|---|---|---|
| 今日の東京の天気は。 | 3,427 | 49 |
| 今日のニュースは。 | 4,639 | 47 |
| 今のドル円は? | 4,663 | 48 |
検索ありでは入力が3,000トークン以上増えているので、検索結果はプロンプトに足されている。
それでも天気の返事は「2026年10月20日(今日)の東京のリアルタイム天気データが含まれていない」だった。
システムプロンプトを付けずに聞くと、「知识库(中国語で知識ベース)の情報によると、今日(2026年10月16日)の東京の天気は」と、4日前の日付の天気を答えた。ドル円を聞くと、2022年4月ごろのレートが返ってきた。
つまり、検索で取ってきた中に当日の東京の天気が入っていなかったので、Qwenは「わからない」と答えていた。
キャラクター設定は関係なかった
システムプロンプトには「書かれている内容は具体的に答え、書かれていないことは知らないと言う。」という一文がある。これが検索結果を使わせていない可能性も考えた。
そこで0時3分の質問を、実際のプロンプトのまま、この一文を外したもの、記憶の部分を外したものの3通りで4回ずつ送った。
| プロンプト | 「わからない」と答えた回数 |
|---|---|
| 実際のプロンプトのまま | 4回中4回 |
| 「知らないと言う」の一文を外した | 4回中4回 |
| 記憶の部分を外した | 4回中4回 |
12回とも「わからない」で、プロンプトの書き方を変えても返事は変わらなかった。
内蔵の検索がどこから取ってきているか
次に、内蔵の検索がどこから情報を取ってきているのか、出典のURLとサイト名を全部書いて、と頼んでみた。
返事に書かれた出典は「中国天气网(中央气象台データ)」で、URLは「提供テキスト内にURLは含まれていません」。LLMが自分で書いた出典なので、本当にそこから取ってきたかは確かめようがない。
返事の中には10月16日から19日までの、日付の違う東京の天気も混ざっていた。
AlibabaのDashScopeには、検索の出典を返させる search_options という指定がある。これがModelScope経由でも使えるかを試した。
| 指定 | 結果 |
|---|---|
出典を返す(enable_source) | 応答に新しい項目は増えず、入力トークン数も指定なしと同じ |
引用を付ける(enable_citation) | 同上 |
| 存在しない指定 | 同上。エラーにもならない |
検索方式 agent | 400エラー。このモデルでは使えない |
検索方式 max | 入力トークン数も答えも変わった |
agent でエラーが返り、max で結果が変わったので、指定自体はAlibaba側まで届いている。
それでも出典は返ってこず、検索先や地域を選ぶ指定もなかった。
同じ時間帯に日時だけのプロンプトで聞くと、「小雨、最高気温24〜26℃」と10月20日の天気として答えたこともあった。
気象庁の予報では、20日の東京は「くもり 所により夕方まで雨」で最高27℃なので、合っていない。検索方式を max にしたときは、「最高・最低ともに0℃、非常に寒い」という予報まで返ってきた。
内蔵の検索では、当日の天気が入っていないことがあり、入っていても気象庁の予報と合わず、出典も返ってこない。ドル円は古く、ニュースには中国語の訳が混ざっていた。
そこで内蔵の検索はやめて、検索をサーバー側で用意することにした。
Qwenにツールを渡す
関数呼び出し(function calling)では、LLMにツールの名前と説明を渡しておく。LLMは必要だと判断すると、「このツールをこの引数で呼んで」という返事を返す。
LLMが自分で検索するわけではなく、実際に検索するのはサーバー側のPythonのコードで、その結果をもう一度LLMに送ると、それを使って返事を作る。
ModelScopeのQwen3.8-Maxでこれが使えるか、web_search というツールを1つ渡して6つの質問で試した。
| 質問 | ツールを呼んだか | 検索語 |
|---|---|---|
| 今日のニュースは。 | 呼んだ | 2026年10月20日 ニュース |
| 今のドル円は? | 呼んだ | ドル円 為替レート 現在 |
| 昨日の日本シリーズどうなった? | 呼んだ | 日本シリーズ 2026年10月19日 結果 |
| 眠くなってきた。 | 呼ばない | - |
| 富士山の高さは? | 呼ばない | - |
| 鈴木さんのとこ出かけてくるね。 | 呼ばない | - |
雑談や知っていることには検索を使わず、新しい情報がいる3問だけでツールを呼んでいた。検索語には日付も入っている。
検索に使うサービス
検索に何を使うかは使える検索APIを調べてから選んだ。
GoogleのCustom Search JSON APIは新規の受け付けを終えていて、既存の利用者も2027年1月1日で使えなくなる。MicrosoftのBing Search APIは2025年8月11日に廃止された。
そこで、追加の費用がかからないddgsから試した。
ddgsはDuckDuckGoなど複数の検索サービスの結果をまとめて取ってくるPythonのライブラリで、このサーバーではAPIキーを設定せずに使っている。問題が出たら、Braveの検索APIに差し替える方針にした。
ddgsで検索して答えさせる
日本・日本語の検索結果を5件取り、タイトルと抜粋とURLをそのままLLMに返した。
| 質問 | 返事 | 全体の時間 |
|---|---|---|
| 今日のニュースは。 | 今日の詳しいニュースの中身まではよくわからなかった | 6.7秒 |
| 今のドル円は? | 1ドル158円40銭くらい | 4.7秒 |
| 昨日の日本シリーズどうなった? | 検索せずに「わからなかった」 | 1.2秒 |
ドル円は検索結果の日経の抜粋にあった「158.41-158.43(10/19 23:59)」の数字を使っていた。
ニュースのほうは、検索結果がNHKの番組ページやニュースサイトの一覧ページばかりで、中身がなかった。
日本シリーズはツールを呼ばずに答えていた。
システムプロンプトに「最新の出来事・ニュース・相場・試合結果など知識に無いことは、推測せずweb_searchで調べてから答える」と書き加えると、検索するようになった。
返事は「今年の日本シリーズは10月24日開幕で、昨日はまだ試合が始まってないよ!」で、検索結果のプロ野球データのページと合っていた。
ニュースはddgsのニュース検索もあわせて使うようにした。
すると今度は、小林薫さん主演のドラマ「深夜食堂6」が7年ぶりに放送開始される日だ、と答えた。検索結果の先頭がこのドラマの放送開始を告知する記事で、今日のニュースとしては外れている。
天気はツールを呼ばずに作り話をした
天気には、気象庁の天気予報のページが読み込んでいる予報のJSONを使うことにした。都道府県ごとに、今日・明日・明後日の予報と1週間分の予報が入っている。
weather というツールを作り、都道府県を指定して予報を取れるようにした。
ところが「今日の東京の天気は。」と聞くと、ツールを呼ばずに「今日の東京は晴れで、最高気温は22度の予想だよ。降水確率は0パーセ」と答えた。繰り返し聞いても同じだった。
20日の東京の予報は「くもり 所により夕方まで雨」なので、これは作り話だ。
同じ条件で聞き方だけを変えると、次のようになった。
| 質問 | ツールを呼んだか |
|---|---|
| 今日の東京の天気は。 | 呼ばない |
| 今日の東京の天気は? | 呼んだ |
| 東京の今日の天気教えて | 呼んだ |
| 今日の大阪の天気は。 | 呼んだ |
| 明日の大阪は雨降る? | 呼んだ |
句点で終わる「今日の東京の天気は。」だけがツールを呼ばなかった。この試験では、句点そのものが原因かまでは確かめていない。
ModelScope側がこっそり検索している可能性も考えて、enable_search: False を明示した場合とも比べた。入力トークン数はどちらも1,176で変わらず、検索結果をプロンプトに足す形の検索はしていなかった。
ツールを呼ぶかどうかをLLMの判断だけに任せると、いちばんよく聞く質問で外れる。
そこで東京の予報のJSONは毎回システムプロンプトに入れておくことにした。ほかの都道府県はこれまでどおり weather で取る。
気象庁の予報は5時・11時・17時に更新されるので、取得した予報は30分の間は取り直さずに使い回す。
2回目の問い合わせで返事が空になる
ドル円を聞くと、返事が空のまま終わることがあった。
1回目の問い合わせでQwenが検索を呼び、その結果を送って2回目を問い合わせると、2回目でもまた検索を呼ぼうとしていた。
サーバー側は2回目の検索の呼び出しを処理していなかったので、何も出力せずに終わっていた。
そこで検索を繰り返せるようにして、1回の返事で検索は最大2回までにした。それでも答えが出ないときは、「ごめんね、うまく調べられなかった。」と返す。
検索は1日100回までに制限し、検索語、取ってきたURL、エラーを search.log に残すようにした。返事がおかしいときに、何をもとに答えたのかを後から調べられる。
タブレットから聞き直す
1時21分、タブレットから同じ「今日の東京の天気は。」を聞くと、今度は答えが返ってきた。
今日の東京はくもりで、所により夜に雨が降る見込みだよ。気温は20度から27度くらいで、夕方までは雨の可能性もあるから傘があると安心だね。
このとき取得した気象庁の東京地方の予報のJSONは19日17時発表の分で、このURLの中身は発表のたびに上書きされる。
それと比べると、20日の「くもり 所により夕方まで雨」と気温の20℃・27℃は合っていたが、「所により夜に雨」は19日の天気の文だった。
予報のJSONには、発表された時点から先の予報が入っている。
1時台はまだ次の5時の発表の前なので、先頭には19日の分が残っていて、その19日夜の文と20日の文が混ざっていた。
まず、予報の値と日時の対応を読むこと、今日より前の日の値は使わないことをプロンプトに書いた。
これで「今日の東京の天気は」「今日傘いるかな」は4回とも正しくなったが、「今夜は雨降る?」には4回とも19日夜の文で答えた。
そこで、期間が終わった予報を消してからLLMに送るようにした。
天気や降水確率のような時間帯ごとの予報は、次の時間帯が始まった時点で消す。気温は朝の最低と日中の最高という時点の値なので、日付が過ぎたものだけ消す。
| 1時台に「今夜は雨降る?」 | 答えた予報 |
|---|---|
| 消す前 | 4回とも19日夜の予報 |
| 消した後 | 4回とも20日の予報 |
週間予報には、文章の天気がなく数字の天気コードしか入っていない日がある。
プロンプトには、コードの百の位を主な天気(1が晴れ、2がくもり、3が雨、4が雪)として扱うという説明と、今日から1週間分の日付と曜日を書き加えた。
「伝えるね」で終わったニュース
1時40分、タブレットから「ヤフーニュースから最新のニュース一覧取ってきて」と頼んだ。文字起こしでは「一覧」が「一見」になっている。
返事は「ヤフーニュースの最新記事は取得できないので、代わりに最新のニュースを検索して伝えるね。」の1文だけだった。
Qwenはサイトを開けないと断る途中で「検索して伝えるね」と言い、検索を呼ばないまま返事を終えていた。
同じ質問を何度か送ると、検索して記事の話題を2つ答えることもあれば、「最新記事一覧を取得する機能はないから、わからないな」と断ることもあった。
見出しはRSSから取る
RSSは、ニュースサイトなどが記事の見出しやURLの一覧を決まった形式で配信しているデータだ。
ニュースの一覧を聞かれたときに検索で探すのはやめて、news というツールを作り、Yahoo!ニュースとNHKのRSSを取ってくるようにした。
| 取得元 | ジャンル | 中身 |
|---|---|---|
| Yahoo!ニュース | 主要・国内・国際・経済・エンタメ・スポーツ・IT・科学・地域 | 見出し |
| NHK | 主要・社会・暮らし・科学文化・政治・経済・国際・スポーツ | 見出しと要約。新しい順に15件まで |
RSSは0.3〜0.7秒で取れて、ニュースの返事は全体で約4秒だった。
特定の話題を詳しく聞かれたときは、これまでどおり web_search を使う。
ツールを呼ばずに古いニュースを答える
RSSを入れた後も、「何かニュースある?」と聞くと、3回中2回はツールを呼ばずに答えた。
話していたのは2021年のノーベル物理学賞などの過去のニュースで、それを今日のこととして答えていた。「今日のニュースは。」でも、ツールを呼ばずに過去のニュースを答えることがあった。
そこで、聞き取った文に「ニュース」が入っているときは、最初の問い合わせからツールの呼び出しを必須にした。APIの tool_choice="required" を付けると、LLMは必ずツールを呼ぶ返事を返す。
ほかの質問でも、返事の最後の文が「調べるね」「検索して伝えるね」のような予告で終わっていて、ツールを呼んでいなければ、呼び出しを必須にしてもう1回問い合わせる。
「検索して調べられるよ」のような申し出は、予告とは別に扱う。
ニュースの返事は全部読み上げると長いので、見出しは2本まで、全体で70字くらいまでにした。
| 質問 | 返事(1文目までの時間) |
|---|---|
| 何かニュースある? | Yahoo!ニュースの主要から見出し2本(4.2秒) |
| スポーツのニュースある? | Yahoo!ニュースのスポーツから見出し2本(3.6秒) |
| NHKのニュース教えて | NHKの主要から見出し2本(3.8秒) |
| ヤフーニュースから最新のニュース一覧取ってきて。 | Yahoo!ニュースの主要から見出し2本(3.8秒) |
作り直した後の返事
| 質問 | 結果 |
|---|---|
| 今日の東京の天気、傘、週末、明日の大阪 | 気象庁の予報どおり |
| 昨日の日本シリーズどうなった? | 試合はなく、10月24日にDeNA対ソフトバンクで開幕 |
| ニュースの一覧 | RSSの見出しから2本 |
| 今のドル円は? | 3回中1回だけ値(158円台前半)を答えた |
| 富士山の高さ、眠くなってきた | 検索せずに答えた |
1文目までの時間は検索する返事で5〜8秒、検索しない返事で1.5〜2秒だった。東京の天気はプロンプトに入れてあるので、検索せずに答えた。
ドル円は、検索結果の抜粋にレートが入っていないことが多かった。
ddgsでは、ニュースと通常の検索のどちらかが「結果なし」のエラーを返すことがときどきあり、そのときはもう片方の結果で答えていた。