Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Créez une application de génération augmentée par récupération (RAG) qui répond aux questions sur une collection de documents, entièrement sur votre appareil. RAG combine la recherche basée sur l’incorporation avec un modèle de conversation afin que les réponses soient ancrées dans vos propres données plutôt que de s’appuyer uniquement sur les connaissances de formation du modèle.
Dans ce tutoriel, vous allez apprendre à :
- Configurer un projet et installer le Kit de développement logiciel (SDK) Local Foundry
- Créer une base de connaissances de documents texte
- Générer des incorporations pour les documents
- Rechercher des documents pertinents par similarité
- Générer des réponses ancrées dans le contexte récupéré
- Nettoyer les ressources
Conditions préalables
- Un ordinateur Windows, macOS ou Linux avec au moins 8 Go de RAM.
- Python 3.11 ou version ultérieure installée.
Installer des packages
Si vous développez ou expédiez sur Windows, sélectionnez l'onglet Windows. Le package Windows s’intègre au runtime Windows ML . Il fournit la même surface d’surface d’API avec une étendue plus large d’accélération matérielle.
pip install foundry-local-sdk-winml openai
Créer une base de connaissances
Une application RAG a besoin d’une collection de documents à rechercher. Définissez une liste de chaînes de texte qui servent de base de connaissances. Dans une application de production, la liste peut être des paragraphes à partir de fichiers, d’enregistrements de base de données ou d’une autre source de texte.
Créez un fichier appelé main.py et ajoutez le code suivant :
import math
from foundry_local_sdk import Configuration, FoundryLocalManager
# Knowledge base — each string represents a document
documents = [
"Foundry Local runs AI models directly on your device without cloud connectivity.",
"The Foundry Local SDK supports Python, C#, JavaScript, and Rust.",
"Embedding models convert text into numerical vectors for similarity search.",
"Foundry Local uses ONNX Runtime for efficient model inference on CPUs and GPUs.",
"The model catalog provides pre-optimized models that you can download and run locally.",
"Retrieval-augmented generation grounds model responses in your own data.",
"Vector similarity search finds documents that are semantically close to a query.",
"Chat completions generate natural language responses from a prompt and context.",
]
Générer des incorporations de documents
Initialisez le SDK, chargez un modèle d’incorporation et convertissez chaque document en vecteur numérique. Ces vecteurs représentent la signification sémantique de chaque document et permettent la recherche de similarité.
Ajoutez le code suivant à main.py:
def main():
# Initialize the SDK
config = Configuration(app_name="foundry_local_rag")
FoundryLocalManager.initialize(config)
manager = FoundryLocalManager.instance
# Load the embedding model
embedding_model = manager.catalog.get_model("qwen3-embedding-0.6b")
embedding_model.download(
lambda p: print(f"\rDownloading embedding model: {p:.1f}%", end="", flush=True)
)
print()
embedding_model.load()
embedding_client = embedding_model.get_embedding_client()
# Embed all documents in a single batch call
response = embedding_client.generate_embeddings(documents)
doc_embeddings = [item.embedding for item in response.data]
print(f"Indexed {len(doc_embeddings)} documents.")
La generate_embeddings méthode accepte une liste de chaînes et retourne un vecteur par entrée. Chaque vecteur capture la signification sémantique du texte, de sorte que des documents similaires produisent des vecteurs proches dans l’espace d’incorporation.
Rechercher des documents pertinents
Pour rechercher des documents liés à une requête, comparez l’incorporation de la requête avec celle de chaque document en utilisant la similarité cosinus. La similarité cosinus mesure la proximité de deux vecteurs dans la direction, quelle que soit l’ampleur. Les valeurs proches de 1,0 indiquent une similarité élevée.
Ajoutez les fonctions d’assistance suivantes ci-dessus main() dans main.py:
def cosine_similarity(a, b):
"""Compute cosine similarity between two vectors."""
dot = sum(x * y for x, y in zip(a, b))
norm_a = math.sqrt(sum(x * x for x in a))
norm_b = math.sqrt(sum(x * x for x in b))
return dot / (norm_a * norm_b) if norm_a and norm_b else 0.0
def find_relevant(query_embedding, doc_embeddings, top_k=2):
"""Return the indices and scores of the top-k most similar documents."""
scores = []
for i, doc_emb in enumerate(doc_embeddings):
score = cosine_similarity(query_embedding, doc_emb)
scores.append((i, score))
scores.sort(key=lambda x: x[1], reverse=True)
return scores[:top_k]
La find_relevant fonction classe tous les documents par similarité et retourne les correspondances supérieures. Cette approche fonctionne bien pour les petites collections. Pour les jeux de données plus volumineux, envisagez une base de données vectorielle dédiée.
Générer des réponses ancrées
Chargez un modèle de conversation et combinez les documents récupérés avec la question de l’utilisateur dans une invite système. Le modèle de conversation utilise le contexte fourni pour générer une réponse fondée sur vos documents.
Ajoutez le code suivant à la main() fonction, après la section d’incorporation :
# Load the chat model
chat_model = manager.catalog.get_model("qwen2.5-0.5b")
chat_model.download(
lambda p: print(f"\rDownloading chat model: {p:.1f}%", end="", flush=True)
)
print()
chat_model.load()
chat_client = chat_model.get_chat_client()
print("\nModels loaded. Ready for questions.")
print("\nThe knowledge base contains information about:")
print(" - Foundry Local features and architecture")
print(" - Supported programming languages")
print(" - Embedding models and vector search")
print(" - ONNX Runtime inference")
print(" - The model catalog")
print(" - RAG and chat completions")
print("\nExample questions:")
print(' "What programming languages does the SDK support?"')
print(' "How does Foundry Local run models?"')
print(' "What is retrieval-augmented generation?"')
print('\nType "quit" to exit.\n')
# Interactive query loop
while True:
query = input("Question: ").strip()
if not query or query.lower() == "quit":
break
# Embed the query
query_response = embedding_client.generate_embedding(query)
query_embedding = query_response.data[0].embedding
# Retrieve the most relevant documents
results = find_relevant(query_embedding, doc_embeddings, top_k=2)
context = "\n".join(f"- {documents[i]}" for i, _ in results)
# Build the prompt with retrieved context
messages = [
{
"role": "system",
"content": (
"Answer the user's question using only the provided context. "
"If the context doesn't contain enough information, say so.\n\n"
f"Context:\n{context}"
),
},
{"role": "user", "content": query},
]
# Stream the response
print("Answer: ", end="", flush=True)
for chunk in chat_client.complete_streaming_chat(messages):
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
print("\n")
# Clean up
embedding_model.unload()
chat_model.unload()
print("Models unloaded. Done!")
if __name__ == "__main__":
main()
L’invite système indique au modèle de répondre à l’aide uniquement du contexte récupéré. L’invite système maintient les réponses ancrées dans vos documents et diminue le nombre de réponses incorrectes. La sortie de diffusion en continu imprime chaque jeton à mesure qu’il est généré, ce qui rend la réponse interactive.
Code complet
Voici l’application complète qui combine toutes les étapes :
import math
from foundry_local_sdk import Configuration, FoundryLocalManager
# Knowledge base
documents = [
"Foundry Local runs AI models directly on your device without cloud connectivity.",
"The Foundry Local SDK supports Python, C#, JavaScript, and Rust.",
"Embedding models convert text into numerical vectors for similarity search.",
"Foundry Local uses ONNX Runtime for efficient model inference on CPUs and GPUs.",
"The model catalog provides pre-optimized models that you can download and run locally.",
"Retrieval-augmented generation grounds model responses in your own data.",
"Vector similarity search finds documents that are semantically close to a query.",
"Chat completions generate natural language responses from a prompt and context.",
]
def cosine_similarity(a, b):
"""Compute cosine similarity between two vectors."""
dot = sum(x * y for x, y in zip(a, b))
norm_a = math.sqrt(sum(x * x for x in a))
norm_b = math.sqrt(sum(x * x for x in b))
return dot / (norm_a * norm_b) if norm_a and norm_b else 0.0
def find_relevant(query_embedding, doc_embeddings, top_k=2):
"""Return the indices and scores of the top-k most similar documents."""
scores = []
for i, doc_emb in enumerate(doc_embeddings):
score = cosine_similarity(query_embedding, doc_emb)
scores.append((i, score))
scores.sort(key=lambda x: x[1], reverse=True)
return scores[:top_k]
def main():
# Initialize the SDK
config = Configuration(app_name="foundry_local_rag")
FoundryLocalManager.initialize(config)
manager = FoundryLocalManager.instance
# Load the embedding model
embedding_model = manager.catalog.get_model("qwen3-embedding-0.6b")
embedding_model.download(
lambda p: print(f"\rDownloading embedding model: {p:.1f}%", end="", flush=True)
)
print()
embedding_model.load()
embedding_client = embedding_model.get_embedding_client()
# Embed all documents
response = embedding_client.generate_embeddings(documents)
doc_embeddings = [item.embedding for item in response.data]
print(f"Indexed {len(doc_embeddings)} documents.")
# Load the chat model
chat_model = manager.catalog.get_model("qwen2.5-0.5b")
chat_model.download(
lambda p: print(f"\rDownloading chat model: {p:.1f}%", end="", flush=True)
)
print()
chat_model.load()
chat_client = chat_model.get_chat_client()
print("\nModels loaded. Ready for questions.")
print("\nThe knowledge base contains information about:")
print(" - Foundry Local features and architecture")
print(" - Supported programming languages")
print(" - Embedding models and vector search")
print(" - ONNX Runtime inference")
print(" - The model catalog")
print(" - RAG and chat completions")
print("\nExample questions:")
print(' "What programming languages does the SDK support?"')
print(' "How does Foundry Local run models?"')
print(' "What is retrieval-augmented generation?"')
print('\nType "quit" to exit.\n')
# Interactive query loop
while True:
query = input("Question: ").strip()
if not query or query.lower() == "quit":
break
# Embed the query
query_response = embedding_client.generate_embedding(query)
query_embedding = query_response.data[0].embedding
# Retrieve the most relevant documents
results = find_relevant(query_embedding, doc_embeddings, top_k=2)
context = "\n".join(f"- {documents[i]}" for i, _ in results)
# Build the prompt with retrieved context
messages = [
{
"role": "system",
"content": (
"Answer the user's question using only the provided context. "
"If the context doesn't contain enough information, say so.\n\n"
f"Context:\n{context}"
),
},
{"role": "user", "content": query},
]
# Stream the response
print("Answer: ", end="", flush=True)
for chunk in chat_client.complete_streaming_chat(messages):
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
print("\n")
# Clean up
embedding_model.unload()
chat_model.unload()
print("Models unloaded. Done!")
if __name__ == "__main__":
main()
Exécutez l’application :
python main.py
Vous voyez une sortie similaire à :
Downloading embedding model: 100.0%
Indexed 8 documents.
Downloading chat model: 100.0%
Models loaded. Ready for questions.
The knowledge base contains information about:
- Foundry Local features and architecture
- Supported programming languages
- Embedding models and vector search
- ONNX Runtime inference
- The model catalog
- RAG and chat completions
Example questions:
"What programming languages does the SDK support?"
"How does Foundry Local run models?"
"What is retrieval-augmented generation?"
Type "quit" to exit.
Question: What programming languages does the SDK support?
Answer: The Foundry Local SDK supports Python, C#, JavaScript, and Rust.
Question: quit
Models unloaded. Done!
Nettoyer les ressources
Les poids du modèle restent dans votre cache local après avoir déchargé un modèle. La prochaine fois que vous exécutez l’application, l’étape de téléchargement est ignorée et les modèles se chargent plus rapidement. Aucun nettoyage supplémentaire n’est nécessaire, sauf si vous souhaitez récupérer de l’espace disque.