0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

概要

私は2024年4月入社の新人社員である。
プログラム経験は趣味でチラッと学んだ程度で、ないと言って差し支えない。
現在はAI系エンジニアとして働いているが、そもそもプログラムすらかけないので何もできない状態が続いている。現状を脱するためにこうして自身で学んだものをアウトプットする場を設けた。
初めての投稿なので多めに見てくれるとありがたいです。

今回の議題

今回はAIの簡単なRAGをpythonで作っていた時に発生した問題である。

これは実際のコードである。 ※外部公開用に少し簡略化、縮小してるので動くかは不明

コード
# Logger setup
def setup_logger(log_dir="logs", level=logging.INFO):
    os.makedirs(log_dir, exist_ok=True)
    logger = logging.getLogger("app")
    logger.setLevel(level)
    handler = RotatingFileHandler(
        os.path.join(log_dir, "app.log"), maxBytes=1_000_000, backupCount=3
    )
    handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
    logger.addHandler(handler)
    return logger

app = Flask(__name__)
logger = setup_logger()

# Simple search simulation
def perform_search(query, top_n=3):
    logger.info(f"Performing search for: {query}")
    return {"results": [f"Result {i+1}" for i in range(top_n)]}

# LLM response simulation
def query_llm(context, user_input):
    logger.info("Querying LLM...")
    return f"LLM response for '{user_input}' with context."

@app.route("/api/query", methods=["POST"])
def handle_request():
    try:
        data = request.get_json()
        user_input = data.get('msg')
        if not user_input:
            raise ValueError("Missing 'msg' parameter")
        
        results = perform_search(user_input)
        context = "\n".join(results["results"])
        response = query_llm(context, user_input)
        
        return jsonify({"response": response})
    except Exception as e:
        logger.error(f"Error: {str(e)}")
        return jsonify({"message": "An error occurred."}), 500

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=False)

簡単なflaskを使ったコードで、"request"を別ページで受け取り、json形式にしたのちlocalhostのurl経由で受け取っている。 その時にログを一つ一つ確認していると"msg"と"results"の内容が代替文字(黒いひし形のはてなマークなど)に置き換わってしまっていた。

コードにもある通り直前でutf-8にデコードしているし、入力側でもutf-8にするよう明示的に処理をしている。
これの原因がわからず苦戦していたのが今回の問題である。

原因

原因はかなり簡単なもので、ログを記述するときに文字化けが発生したようだった。そのため、ログ以外の処理はそのままでも問題なく進んでいた。
かなりの時間悩んでいたので拍子抜けだったが、こういう部分も確認しなくてはならないのだなと勉強にはなった。

解決策

解決策はシンプルで、ログの関数部分で文字コードを指定してするだけで解決できた。
(ログを関数にする意味あるか?という疑問は置いておいてください、、)

def setup_logger(name=__name__, log_dir="logs", level=logging.DEBUG):
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    logger = logging.getLogger(name)
    logger.setLevel(level)
    logger.handlers.clear()

    log_file = os.path.join(log_dir, "app.log")
    handler = RotatingFileHandler(
        log_file, 
        maxBytes=10_000_000, 
        backupCount=5,
        encoding="utf-8")
    formatter = logging.Formatter(
        "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    )
    handler.setFormatter(formatter)
    logger.addHandler(handler)

    return logger

これで出力してみると、無事文字化けせずにログを出力することができた。

まとめ

今回はかなり初歩的な内容でしたが、みんなこういった道を通っているのだと信じて進みたいと思う。
第一歩としてこういった備忘録は大事だと常々感じさせられるので、三日坊主にならず気づいたことがあれば投稿していきたい。
最初のつたない記事をお読みいただきありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?