Semantic Code Search
On this page
Search Code by Meaning
Traditional code search relies on keywords: you type a function name or a word from a comment. Semantic code search goes further: it finds code by its meaning or intent, even if the exact terms don’t match.
With codestral-embed, you can search for code using natural language. A query like “function that sorts a list” will find a quicksort implementation even if the word “sort” never appears in the code. This mirrors the daily reality of a developer joining an existing project: you know what you’re looking for, but you have no idea how the previous team named it.
Indexing a Code Directory
The first step is to extract and encode every file or function in a project. The function below walks the directory tree and filters out folders that would clutter the index. node_modules alone can be ten times larger than the code you actually wrote, and none of its files are relevant to your search.
import os
import numpy as np
from mistralai.client import Mistral
client = Mistral(api_key=api_key)
def extract_code_files(directory, extensions=(".py", ".js", ".ts")):
"""Extract all code files from a directory."""
code_files = []
for root, dirs, files in os.walk(directory):
# Ignore irrelevant directories
dirs[:] = [d for d in dirs if d not in ("node_modules", ".git", "__pycache__", "venv")]
for f in files:
if any(f.endswith(ext) for ext in extensions):
filepath = os.path.join(root, f)
with open(filepath, "r", encoding="utf-8", errors="ignore") as fh:
content = fh.read()
if content.strip():
code_files.append({
"path": filepath,
"content": content[:4000], # Truncate if too long
})
return code_files
# Extract files
code_files = extract_code_files("./my-project/")
print(f"{len(code_files)} code files found")
Two implementation details deserve attention. Modifying dirs[:] in place isn’t just shorthand; it’s the only way to prevent os.walk from descending into those directories. Reassigning the variable without slicing it would have no effect. As for truncating at 4,000 characters, this protects you from monstrous files that would blow up the request, while keeping the file header—imports, main definitions—which carries the most significant signal.
Encoding and Indexing
Encoding happens in batches of twenty files, with a progress display. On a repository with several hundred files, this loop runs for several minutes. Without a counter, you have no way to distinguish slow processing from a stuck call.
def index_code_files(code_files, batch_size=20):
"""Create embeddings for all code files."""
all_embeddings = []
for i in range(0, len(code_files), batch_size):
batch = code_files[i:i + batch_size]
inputs = [f["content"] for f in batch]
response = client.embeddings.create(
model="codestral-embed",
inputs=inputs,
)
all_embeddings.extend([d.embedding for d in response.data])
print(f"Encoded {min(i + batch_size, len(code_files))}/{len(code_files)}")
return np.array(all_embeddings)
embeddings = index_code_files(code_files)
print(f"Index: {embeddings.shape}")
The order of embeddings in the matrix exactly matches the order of code_files. This implicit correspondence is the pivot for everything that follows: it allows an index returned by the ranking to point to a specific file path.
Natural Language Search
The major advantage of codestral-embed is that you can search using a question in French or English. The function encodes the query with the same model, calculates similarities against the entire index, and returns the top_k best results along with a content preview.
from sklearn.metrics.pairwise import cosine_similarity
def search_code(query, code_files, embeddings, top_k=5):
"""Search for code using natural language descriptions."""
# Encode the query
response = client.embeddings.create(
model="codestral-embed",
inputs=[query],
)
query_emb = np.array(response.data[0].embedding)
# Calculate similarities
sims = cosine_similarity([query_emb], embeddings)[0]
# Top-k results
top_indices = np.argsort(sims)[::-1][:top_k]
results = []
for idx in top_indices:
results.append({
"path": code_files[idx]["path"],
"score": float(sims[idx]),
"preview": code_files[idx]["content"][:200],
})
return results
# Natural language searches
queries = [
"email validation function",
"database connection",
"HTTP error handling",
"sorting algorithm",
]
for query in queries:
print(f"\n--- Query: '{query}' ---")
results = search_code(query, code_files, embeddings, top_k=3)
for r in results:
print(f" [{r['score']:.3f}] {r['path']}")
The preview field has immediate practical utility: it saves you from opening five files to figure out which one actually matches. In an editor integration, these two hundred characters become the preview line displayed under each result.
Cross-Language Search
codestral-embed understands logic regardless of the language. You can search for a Python pattern and find the equivalent in JavaScript:
# Search using a code example in one language...
query_python = "def authenticate(username, password): check credentials and return token"
# ...and find the equivalent in another language
results = search_code(query_python, code_files, embeddings)
# May return a .js file with a similar function
This capability is invaluable for applications split between a Python backend and a TypeScript frontend, where the same business rule is sometimes implemented on both sides. Finding both implementations from a single query helps you spot divergences before a bug reveals them in production.
Search by Function Signature
You can also search by expected form rather than functional domain. Describing the structure—an asynchronous function, a class, middleware, a test—steers the search toward a type of code object rather than a subject.
technical_queries = [
"async function that fetches data from API and handles errors",
"class with CRUD methods for database operations",
"middleware that checks authentication token",
"unit test for user registration",
]
for q in technical_queries:
results = search_code(q, code_files, embeddings, top_k=2)
print(f"\n{q}:")
for r in results:
print(f" -> {r['path']} (score: {r['score']:.3f})")
Try these four queries on your own repository before moving on. You’ll notice that results degrade significantly on very long files, where the 4,000-character truncation cut off the useful part. This is the moment to decide whether to index whole files or, better yet, functions broken down one by one.
Key Takeaways
- codestral-embed lets you search for code using natural language descriptions
- Indexing involves encoding all code files into vectors
- Cross-language search works: a Python pattern finds the JS equivalent
- Filter out irrelevant directories (node_modules, .git, venv) during extraction
- Truncate very long files to stay within model limits