LangMemLangMem 0.0.30 · LangGraph 1.2 · Python 3.10+
Dashboard
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
19 small wins to finish your pathNext lesson →

Semantic search

Semantic search is a store search that ranks items by how close their meaning is to a query, using embeddings, so "I want my money back" finds the refunds note even though the two share no words.

Last updated: 30 Sep, 2026 · LangMem 0.0.30

A customer never phrases a question the way a memory was written. Searching by keywords would miss most matches. Give the store an embedding model and every item is turned into a vector when it is saved; a query is turned into a vector too, and the closest items come back first. That is what makes LangMem's memories findable later.

Vector store memory · from the AI Security Course · 268:19 to 271:50
The video's notebook stores conversation messages in a Chroma vector database it sets up itself. Here the vector search is built into LangGraph's InMemoryStore, and the embeddings come from Gemini.

Every conversation as a vector

The clip walks through the flow: each message is turned into a vector and saved; at the start of a new turn the query, "should I rebalance my portfolio", is embedded, the store finds the nearest vectors, the top k come back, and they go to the model with the current conversation for a personalised answer. The store below does the same with a store's index setting and search(..., query=...).

Syntax:

python
store = InMemoryStore(index={"dims": 3072, "embed": "google_genai:gemini-embedding-2"})
store.search(namespace, query="text to match", limit=3)  # Items with a score, best first

A store with an embedding model

index tells the store to embed every value it saves. dims must match the model's vector length, 3072 for gemini-embedding-2, as printed in Installation and setup.

python
from langgraph.store.memory import InMemoryStore

store = InMemoryStore(index={"dims": 3072, "embed": "google_genai:gemini-embedding-2"})

Three help-desk notes

python
store.put(("faq",), "refunds", {"text": "Refunds reach your card within five working days after we receive the return."})
store.put(("faq",), "delivery", {"text": "Parcels are delivered within three days by courier."})
store.put(("faq",), "password", {"text": "Reset your password from the login page."})

Searching by meaning

ExampleAPI key
from langgraph.store.memory import InMemoryStore

store = InMemoryStore(index={"dims": 3072, "embed": "google_genai:gemini-embedding-2"})
store.put(("faq",), "refunds", {"text": "Refunds reach your card within five working days after we receive the return."})
store.put(("faq",), "delivery", {"text": "Parcels are delivered within three days by courier."})
store.put(("faq",), "password", {"text": "Reset your password from the login page."})

for query in ["I want my money back", "when will my parcel come?"]:
    best = store.search(("faq",), query=query, limit=3)
    print(query)
    for item in best:
        print(f"  {item.score:.3f} {item.key}")

Reading the scores

  • "I want my money back" found refunds first, at 0.649, though the query and the note share no words: "money back" and "refunds" are close in meaning, and the embeddings capture that.
  • "when will my parcel come?" found delivery first, at 0.730.
  • The other notes still score between 0.498 and 0.609. score is the similarity to the query, and unrelated texts do not score near zero with this model. Rank by the order and keep a limit; a fixed cutoff like 0.5 would keep almost everything.

Semantic search vs listing a namespace

store.search(ns)store.search(ns, query=...)
Needs an indexNoYes, an embedding model
OrderAs storedBest match first
scoreNoneSimilarity to the query
CostNothingOne embedding call per query, one per saved item

Where semantic search is used

  • A store manager searching for memories related to a new conversation, in Store managers.
  • An agent's search_memory tool, in Memory tools.
  • Any FAQ or notes lookup where users will not use your exact words.
Watch out. Changing the embedding model changes dims and the meaning of every stored vector. Items embedded with one model cannot be searched with another; re-embed everything when you switch.
Try it yourself
  • Search for "courier" with limit=1.
  • Add "fields": ["text"] to the index and put a value with another field too.
  • Put an item with index=False and search for its text.

Every expert started right here.