summaryrefslogtreecommitdiff
path: root/tests/test_tools.py
AgeCommit message (Collapse)Author
2026-08-26fix(tools): PDFの会話間継続をトークン単独で再開可能にするtanaka takashi
長いPDFを複数会話に分けて取得する際、モデルがurl_or_pathを省略したり、過去の添付IDや古い継続トークンを組み合わせたりして、先頭または以前のページへ戻る問題を改善する。PDFカーソル自体は正しく進んでいたため、汎用LLM層やセッション形式を変更せず、pdf_to_textの入出力契約だけを明確化する。 - continue_fromを自己完結した再開情報として扱い、PDFソース、ページ番号、ページ内文字位置をトークンから復元 - 継続時はurl_or_pathを省略可能にし、競合する値が渡されてもトークン内のソースを優先 - Ollama生成スキーマでもurl_or_pathを任意にして、continue_from単独のツール呼び出しを許可 - 未完了結果へ最新トークン、旧トークンの置換、単独再開、上限時の保持を表すPDF専用メタデータを追加 - 継続メタデータを固定キーと真偽値で表現し、会話言語に依存しない形式へ統一 - 無効トークン時は先頭再試行を禁止し、直前の最新トークンを再利用する機械可読情報を返却 - メタデータをpage-info側へ配置して本文連結を汚さず、結果全体を6000文字以内に再調整 - llm.py、チャット処理、セッションJSON、scrape_url、search_and_fetch、MCPツールは変更しない 検証: - pytest: 132 passed - ruff check: passed - mypy src: passed - 1463891.1463912.pdf: 12ページ、52577文字をcontinue_from単独の10回で完全再構成 - 指定PDFの最大ツール結果長はメタデータ込み5992文字
2026-08-23fix(tools): PDFページングを損失なしカーソル方式へ再設計tanaka takashi
PDF本文をページ単位で抽出した後に文字数上限で切断しつつ、継続位置だけ次ページへ進めていたため、ページ末尾が復元不能になる問題を修正する。ツール側の本文上限とLLM側の結果上限の不整合、25ページの処理上限、添付経路での継続情報欠落も共通契約で解消する。 - 共通PageResultと、メタデータ込みの結果上限内で本文量を決めるフォーマッターを追加 - v2トークンにPDFのページ番号とページ内文字位置を保持し、v1トークンの読み取り互換性を維持 - pdf_to_text、scrape_url、search_and_fetchを返却済み本文だけカーソルが進む方式へ統一 - max_pdf_pagesを文書全体ではなく1呼び出しの処理上限として扱い、長い単一ページと26ページ目以降の継続取得に対応 - attachment:<file_id>をセッション限定で解決し、既存添付も保存済みプレビューではなく元PDFから再解析 - Web取得ファイルをセッションとURL単位で重複排除し、HTMLおよびテキスト経路の全文ページングも維持 - 正常なページング結果の後段切断を禁止し、結果上限・コンテキスト予算・ラウンド上限では未取得状態を明示 - 日英プロンプト、UIメッセージ、ツールスキーマ、変更履歴を実装へ同期 - 実PDF、30ページ超、長い単一ページ、旧トークン、セッション分離、コンテキスト境界の回帰テストを追加 検証: - pytest: 130 passed - ruff check src tests: passed - mypy src: passed - c2144.pdf: 19ページ、抽出本文46015文字(ページ区切り込み46051文字)を8回で重複・欠落なく完全再構成
2026-08-16refactor: streamline chat flow and improve diagnosticstanaka takashi
Store server.log inside OLLAMA_WEB_DATA_DIR and manage the ollama-web file handler through the Starlette lifespan. Close and detach the handler on shutdown to prevent duplicate records and Windows file locks when applications are recreated. Stop converting DuckDuckGo provider failures into empty search results. Record a query-safe traceback, re-raise the original exception, and let ToolRegistry expose the exception type and message as a tool error without adding or spoofing Referer headers. Remove the unused non-streaming chat_with_tools implementation and its private helpers. Move capability, options, standard tool, MCP tool, and final tools=[] regression coverage onto the production streaming path. Add integration coverage for data/server.log placement, handler cleanup, repeated lifespans, and provider 403 diagnostics. Update the Unreleased changelog entry. Validated with 118 tests, Ruff, mypy, diff checks, real DuckDuckGo searches, successful result-page fetches, and observable 401/403 responses from sites that reject automated retrieval.
2026-08-02fix(tools): search_and_fetch のページングトークン破損バグを修正tanaka takashi
## 背景 search_and_fetch の next_token / continue_from によるページング継続が PDF 形式で間欠的に失敗するバグが報告された。発生エラー: 1. payload is not valid JSON: Expecting ':' delimiter 2. 'utf-8' codec can't decode byte 0xda in position 278 1ページ目の取得自体は成功し、next_token 返却まで正常だが、 next_token を continue_from に渡した2ページ目でエラーが発生。 txt/md/csv/json では安定動作し、PDF で間欠的・再現性なし。 ## 根本原因 コード精査の結果、報告の「非UTF-8バイト混入」仮説に対し、より有力な 主因として「トークン巨大化による末尾欠損」を特定: - _render_file_page() は matched 配列(title/href/body 全部入り)を トークンに埋め込んでいたが、レンダリングで使うのは title と href のみ。body(DuckDuckGo のスニペット、PDF 論文要約で数KB)は未使用 - 候補複数件でトークンが数KB〜十数KBに膨張 - LLM が continue_from にコピーする際、コンテキスト長や _trim_tool_result の切り詰めでトークン末尾が欠損 - base64 デコード結果が不正になり JSONDecodeError(JSON途中切断) と UnicodeDecodeError(マルチバイト境界切断)の両エラーが発生 - PDF で間欠的・再現性なしは、検索結果セットごとにスニペット長が 変動しトークンサイズが破損閾値を前後するためと説明がつく 補助要因: make_token() の ensure_ascii=False が、末尾欠損時に マルチバイト文字境界で切れる確率を上げていた。 ## 修正内容(案A: ユーザー承認済み) 1. pagination.py の make_token() を ensure_ascii=True 化 - トークンを純ASCII化し、末尾欠損でも UnicodeDecodeError を防止 - 非ASCII文字は \uXXXX エスケープ(6バイト固定)で安定化 2. fetch.py に _slim_matched() ヘルパーを追加 - matched から body を除外し title+href のみ埋め込み - 3箇所の make_token 呼び出し(fetch失敗時・ファイル内継続時・ 次ファイル移行時)を matched=_slim_matched(matched) に変更 - トークンサイズを数KB〜十数KB → 数百バイトに削減 3. トークン形式バージョン v は 1維持(構造不変・後方互換) - 旧トークン(body入り・ensure_ascii=False)も parse_token で 正常デコード可能 - 再検索回避機能も維持 ## テスト tests/test_tools.py に新規テスト5件を追加: - test_make_token_ensure_ascii_true - test_search_and_fetch_token_excludes_body - test_search_and_fetch_token_size_reduced - test_search_and_fetch_continue_with_slim_token - test_search_and_fetch_pagination_with_nonascii_title ## 検証結果 - pytest: 113 passed (新規5件含む、既存回帰なし) - ruff check src/ tests/: All checks passed - mypy src/: Success: no issues found in 30 source files ## ドキュメント docs/tools-schema.md に実装ベースの差分を反映: - make_token() の説明に ensure_ascii=True 化の旨を追記 - search_and_fetch 処理フローの注記に _slim_matched() による body 除外とトークンサイズ削減の旨を追記 - トークンペイロード構造の matched 例から body を削除
2026-08-02scrape_url / pdf_to_text / search_and_fetch ↵tanaka takashi
はページング(継続トークン方式)に対応 mypy 6エラー修正
2026-06-23基本機能実装tanaka takashi