2
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

🚀[5分でできるRAG入門] 「記憶するAI」爆誕! OpenAIの"忘れっぽい問題"を LangMem で解決する![爆速テンプレート]

Last updated at Posted at 2025-03-16

🧠 OpenAI APIの弱点...。 え、これって Memory機能ないの!!???

👤「昨日の話の続き、覚えてる?」
🤖「申し訳ありませんが、過去の会話は覚えていません。」
👤「チョットマッテ…(゜Д゜)」

これ、もどかしくないですか!?
💡 そこで! LangMem を使って「記憶するAI」を作っちゃいます!
💡 今回は、細かいロジックは一旦置いておいて、まずは動かすところにフォーカスして説明します!

📌 この記事で学べること

  • LangMem を使った 記憶するAI(API)の実装方法
  • 爆速で開発 するためのシンプルなコード
  • さらに進化 させるためのアイデア

最初に考えたこと、なんか解決方法ないかな...。

最近、LangChainからヤバげなリリースがあったことを思い出しました....。

本日、エージェントが長期記憶を通じて学習し、改善するのに役立つライブラリであるLangMem SDKをリリースします。
会話から情報を抽出し、迅速な更新を通じてエージェントの動作を最適化し、行動、事実、イベントに関する長期記憶を維持するためのツールを提供します。

ということで、リリースしたてのLangMemを使っていこうと思いますー!!(え...。ドキュメント全部英語?、日本語のチュートリアルあんまない???💦

1️⃣ まずは環境構築

📌 こんな感じのディレクトリ構成で、ファイルだけ作ってしまってください!

.
├── backend
│   ├── Dockerfile
│   └── api
│       ├── main.py
│       └── routers
│           └── chat.py
└── docker-compose.yaml

📌 Dockerfiledocker-compose.yamlをこんな感じで設定してください!

FROM python:3.11-slim
ENV PYTHONUNBUFFERED=1
ENV OPENAI_API_KEY="your_api_key"

WORKDIR /src
COPY api ./

RUN pip install --upgrade pip
RUN pip install fastapi
RUN pip install "uvicorn[standard]"
RUN pip install requests
RUN pip install langchain
RUN pip install langchain_openai
RUN pip install langgraph
RUN pip install -U langmem
RUN pip install numpy
RUN pip install langchain_community

ENTRYPOINT ["uvicorn", "main:app", "--host", "0.0.0.0", "--reload"]
docker-compose.yaml
version: '3'

services:
  
  demo-api:
    build:
      context: "./backend"
      dockerfile: "Dockerfile"
    ports:
      - "8000:8000"
    volumes:
      - "./backend:/src"
    environment:
      - PYTHONPATH=/src
    working_dir: /src
    entrypoint: ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]

2️⃣ 実際のコード

📌 FastAPIのエントリーポイントを作る。

main.py
from fastapi import FastAPI
from api.routers import chat

app = FastAPI(
    title="BonBon AI",
    description="LangMEM を用いた自己意識型AI",
    version="1.0.0"
)

@app.get("/")
async def root():
    return {"message": "BonBon AI is running!"}

app.include_router(chat.router, prefix="/chat", tags=["Chat"])

# FastAPIアプリの起動(デバッグ用)
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

📌 LangMemを用いてRooterを記述する

chat.py
from typing import Any, Dict, List
from langgraph.store.memory import InMemoryStore
from openai import OpenAI
from langmem import create_manage_memory_tool, create_search_memory_tool
from pydantic import BaseModel
from fastapi import APIRouter

router = APIRouter()

store = InMemoryStore(
    index={
        "dims": 1536,
        "embed": "openai:text-embedding-3-small",
    }
)

class ChatRequest(BaseModel):
    user_id: str
    user_message: str


@router.post("/")
def chat(request: ChatRequest):
    user_id = request.user_id
    user_message = request.user_message

    memory_tools = [
        create_manage_memory_tool(namespace=("memories",user_id), store=store),
        create_search_memory_tool(namespace=("memories",user_id), store=store),
    ]

    result = run_agent(
        tools=memory_tools,
        user_input=user_message,
    )

    user_memories = store.search(("memories",user_id))
    serialized_memories = [memory.dict() for memory in user_memories]

    response = {
        "message": result,
        "memories": serialized_memories
    }

    return response

def execute_tool(tools_by_name: Dict[str, Any], tool_call: Dict[str, Any]) -> str:
    """Execute a tool call and return the result"""
    tool_name = tool_call["function"]["name"]

    if tool_name not in tools_by_name:
        return f"Error: Tool {tool_name} not found"

    tool = tools_by_name[tool_name]
    try:
        result = tool.invoke(tool_call["function"]["arguments"])
        return str(result)
    except Exception as e:
        return f"Error executing {tool_name}: {str(e)}"


def run_agent(tools: List[Any], user_input: str, max_steps: int = 5) -> str:
    """Run a simple agent loop that can use tools"""

    client = OpenAI()
    tools_by_name = {tool.name: tool for tool in tools}

    openai_tools = [
        {
            "type": "function",
            "function": {
                "name": tool.name,
                "description": tool.description,
                "parameters": tool.tool_call_schema.model_json_schema(),
            },
        }
        for tool in tools
    ]

    messages = [{"role": "user", "content": user_input}]

    for step in range(max_steps):
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=messages,
            tools=openai_tools if step < max_steps - 1 else [],
            tool_choice="auto",
        )
        message = response.choices[0].message
        tool_calls = message.tool_calls

        if not tool_calls:
            return message.content

        messages.append(
            {"role": "assistant", "content": message.content, "tool_calls": tool_calls}
        )

        for tool_call in tool_calls:
            tool_result = execute_tool(tools_by_name, tool_call.model_dump())
            messages.append(
                {
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "content": tool_result,
                }
            )

    return "Reached maximum number of steps"

3️⃣ サーバー実行

docker-compose up --build

4️⃣ API実行!!

📌 エンドポイントはここです!

POST http://127.0.0.1:8000/chat

✅ まずは、記憶がないことを確認。
image.png

✅ 次に名前を教えてあげる。
image.png

✅ もう一回質問!
image.png

あなたのAgentも、記憶を持てるようになりましたか...?

これで最小構成は完成です!!!🎉

🚀 もっと進化させるには~~今後やりたいこと。

  • InMemoryStore を PostgreSQL に置き換えて、再起動時にデータを保持できるようにする。
  • 記憶と一緒に感情パラメータを保存させ、記憶想起のweightとして利用すると、より人間らしいリアクションをできるようになるかも。
  • 日本語の情報あんまりないから、作りながらいっぱい記事のネタにしたいと目論んでます😂。

⚙️ Git

本当に励みになるので...。

⭐️ この記事が役に立ったら「いいね」&「ブクマ」よろしくお願いします!

2
6
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
2
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?