LangChain
המדריך המלא בעברית
Framework Python לבניית אפליקציות מבוססות LLM. חיבור מודלי שפה למקורות נתונים, כלים ו-Agents — מ-RAG פשוט ועד Agents אוטונומיים בפרודקשיין.
מה זה LangChain?
LangChain הוא Framework קוד-פתוח לבניית אפליקציות מבוססות מודלי שפה גדולים (LLM). הוא נוצר בנובמבר 2022 על-ידי Harrison Chase ומאז הפך לאחד הפרויקטים הצומחים ביותר ב-GitHub, עם למעלה מ-90,000 stars ומאות תורמים פעילים. LangChain זמין הן ל-Python והן ל-JavaScript/TypeScript.
הבעיה שהוא פותר היא משמעותית: מודלי שפה כמו GPT-4o, Claude ו-Gemini הם כלים חזקים, אבל לבדם הם מוגבלים לידע שהיה ב-Training שלהם ולחלון ה-Context שלהם. LangChain מאפשר לחבר אותם למקורות נתונים חיצוניים — קבצי PDF, בסיסי נתונים, API — ולתת להם כלים לפעולה בעולם האמיתי, כמו חיפוש באינטרנט, חישובים ושליחת מיילים.
הארכיטקטורה של LangChain בנויה מ-4 שכבות עיקריות: Models — עטיפות אחידות למודלי LLM שונים; Prompts — ניהול ותבניות לפרומפטים; Chains — שרשראות לוגיות שמחברות מודלים ופעולות; ו-Agents — מערכות אוטונומיות שמחליטות איזה כלי להפעיל ומתי. גרסת v0.3 הביאה עימה את LCEL (LangChain Expression Language) — תחביר pipe נקי ואנסכרוני שהפך את בניית ה-Chains לאינטואיטיבית הרבה יותר.
התקנה וסביבה
מומלץ להתחיל עם Virtual Environment. LangChain מחולק לחבילות נפרדות כדי שתתקין רק מה שצריך לפרויקט שלך.
התקנת החבילות הבסיסיות
# יצירת סביבה וירטואלית
python -m venv venv
source venv/bin/activate # Linux/Mac
# venv\Scripts\activate # Windows
# התקנת LangChain + ספקי מודלים + כלים שימושיים
pip install langchain langchain-openai langchain-anthropic langchain-community python-dotenv
# לעבודה עם Vector Stores ו-RAG
pip install langchain-chroma chromadb pypdf
# לעבודה עם Pinecone
pip install langchain-pinecone pinecone-client
קובץ .env — ניהול מפתחות API
צור קובץ .env בתיקיית הפרויקט ואל תכניס אותו ל-Git:
# .env
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=ls__...
LANGCHAIN_PROJECT=my-project
# טעינת המפתחות בקוד Python
from dotenv import load_dotenv
load_dotenv()
# עכשיו ניתן להשתמש בכל הכלים
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o")
הוסף .env ל-.gitignore לפני הקומיט הראשון. שימוש ב-python-dotenv הוא הדרך הנכונה לניהול מפתחות בפיתוח. בפרודקשיין — השתמש במשתני סביבה ישירות או בכלי כמו AWS Secrets Manager.
Chains — שרשראות לוגיות
Chain הוא רצף של פעולות שמחוברות יחד. הקלט של כל שלב הוא הפלט של השלב הקודם. LangChain v0.3 מציג שני אופני עבודה עיקריים: ה-API הישן של LLMChain ו-LCEL החדש.
LLMChain — הדרך הקלאסית
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser
# הגדרת הרכיבים
llm = ChatOpenAI(model="gpt-4o", temperature=0.3)
prompt = ChatPromptTemplate.from_messages([
("system", "אתה מומחה לסיכום טקסטים בעברית. סכם בצורה תמציתית ב-3 נקודות."),
("human", "{text}")
])
output_parser = StrOutputParser()
# שרשרת עם LCEL — pipe syntax
chain = prompt | llm | output_parser
# הרצה
result = chain.invoke({"text": "הטקסט שלך כאן..."})
print(result)
LCEL — LangChain Expression Language
LCEL הוא תחביר ה-pipe (|) שמאפשר לשרשר רכיבים בצורה קריאה ואנסכרונית. כל רכיב שמממש את ממשק Runnable ניתן לחיבור בשרשרת.
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.schema import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
# שרשרת סיכום מסמך עברי
summarize_prompt = PromptTemplate.from_template(
"סכם את המסמך הבא בעברית בין 3 ל-5 משפטים:\n\n{document}"
)
translate_prompt = PromptTemplate.from_template(
"תרגם את הסיכום הבא לאנגלית:\n\n{summary}"
)
llm = ChatOpenAI(model="gpt-4o")
parser = StrOutputParser()
# שרשרת דו-שלבית: סיכום → תרגום
chain = (
{"document": RunnablePassthrough()}
| summarize_prompt
| llm
| parser
| {"summary": RunnablePassthrough()}
| translate_prompt
| llm
| parser
)
result = chain.invoke("כאן יבוא הטקסט העברי שרוצים לסכם ולתרגם...")
print(result)
Sequential Chains — שרשראות מורכבות
לשרשראות מורכבות עם כמה שלבים ומשתנים מרובים, ניתן לבנות Chains מקוננות:
from langchain_core.runnables import RunnableParallel
# עיבוד מקביל — שני חישובים בו-זמנית
parallel_chain = RunnableParallel(
summary=summarize_prompt | llm | parser,
keywords=keyword_prompt | llm | parser
)
# ריצה מקבילית — מהירה יותר
result = parallel_chain.invoke({"document": document_text})
print("סיכום:", result["summary"])
print("מילות מפתח:", result["keywords"])
כל Chain שנבנה עם LCEL תומך אוטומטית ב-await chain.ainvoke() ו-chain.astream() לסטרימינג. זה חיוני לבניית ממשקי משתמש תגובתיים שמציגים את הטקסט תוך כדי יצירתו.
RAG עם LangChain — Retrieval Augmented Generation
RAG היא טכניקה שמאפשרת למודל שפה לענות על שאלות מבוססות מידע מסמכים שלא היו ב-Training שלו. LangChain מספק את כל הכלים הנחוצים: טעינת מסמכים, פיצול, יצירת Embeddings ואחזור.
שלב 1 — טעינת מסמכים
from langchain_community.document_loaders import (
PyPDFLoader,
WebBaseLoader,
DirectoryLoader,
TextLoader
)
# טעינת PDF
loader = PyPDFLoader("document.pdf")
pages = loader.load() # רשימת Document objects
# טעינת אתר אינטרנט
web_loader = WebBaseLoader("https://example.com/article")
docs = web_loader.load()
# טעינת כל קבצי ה-PDF בתיקייה
dir_loader = DirectoryLoader("./documents/", glob="**/*.pdf", loader_cls=PyPDFLoader)
all_docs = dir_loader.load()
print(f"נטענו {len(all_docs)} מסמכים")
שלב 2 — פיצול טקסט (Text Splitting)
from langchain.text_splitter import RecursiveCharacterTextSplitter
# פרמטרים חשובים:
# chunk_size — גודל כל קטע בתווים
# chunk_overlap — חפיפה בין קטעים סמוכים (מונע אובדן הקשר)
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
length_function=len,
separators=["\n\n", "\n", ".", " ", ""]
)
chunks = splitter.split_documents(all_docs)
print(f"נוצרו {len(chunks)} קטעים")
שלב 3 — Embeddings ו-Vector Store
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
# יצירת Embeddings
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# שמירה ב-Chroma (מקומי, ללא צורך בשרת)
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db"
)
# טעינה מחדש בהרצות עתידיות
vectorstore = Chroma(
persist_directory="./chroma_db",
embedding_function=embeddings
)
שלב 4 — RetrievalQA Chain מלאה
דוגמה מלאה: RAG על קובץ PDF בעברית עם מענה בעברית:
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# --- טעינה ועיבוד ---
loader = PyPDFLoader("hebrew_document.pdf")
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=800, chunk_overlap=150)
chunks = splitter.split_documents(docs)
# --- Vector Store ---
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(chunks, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
# --- Prompt בעברית ---
hebrew_prompt = PromptTemplate(
input_variables=["context", "question"],
template="""ענה על השאלה הבאה בעברית בלבד, בהתבסס על ההקשר המסופק.
אם התשובה אינה במסמך, אמור "המידע אינו נמצא במסמך".
הקשר:
{context}
שאלה: {question}
תשובה:"""
)
# --- Chain ---
llm = ChatOpenAI(model="gpt-4o", temperature=0)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
chain_type_kwargs={"prompt": hebrew_prompt},
return_source_documents=True
)
# --- שאילתא ---
result = qa_chain.invoke({"query": "מה המסקנות העיקריות של המסמך?"})
print("תשובה:", result["result"])
print("מקורות:", [doc.metadata for doc in result["source_documents"]])
עבור טקסטים עבריים, chunk_size=800-1200 עובד טוב. קטעים קצרים מדי יאבדו הקשר; ארוכים מדי יאטו את ה-Retrieval ויעלו עלויות. ה-chunk_overlap של 15-20% מגודל הקטע מונע אובדן מידע בגבולות.
Agents ו-Tools
Agent הוא מערכת שמשתמשת ב-LLM כמנוע חשיבה כדי להחליט על רצף פעולות. בניגוד ל-Chain שרצף הפעולות שלה ידוע מראש, Agent בוחר דינמית אילו Tools להפעיל ומתי, בהתבסס על התוצאות הביניים.
Agent בסיסי עם Tools מובנים
from langchain_openai import ChatOpenAI
from langchain.agents import initialize_agent, AgentType
from langchain_community.tools import WikipediaQueryRun, DuckDuckGoSearchRun
from langchain_community.utilities import WikipediaAPIWrapper
from langchain.tools import Tool
import math
# Tools מובנים
wikipedia_tool = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())
search_tool = DuckDuckGoSearchRun()
# Tool מותאם אישית עם פונקציה רגילה
def calculator(expression: str) -> str:
"""מחשב ביטוי מתמטי. קלט: string כמו '2 + 2' או 'sqrt(16)'"""
try:
result = eval(expression, {"__builtins__": {}}, {"sqrt": math.sqrt, "pi": math.pi})
return str(result)
except Exception as e:
return f"שגיאה: {e}"
calc_tool = Tool(
name="Calculator",
func=calculator,
description="מחשב ביטויים מתמטיים. שימושי לחישובים מספריים."
)
# הגדרת ה-Agent
llm = ChatOpenAI(model="gpt-4o", temperature=0)
agent = initialize_agent(
tools=[wikipedia_tool, search_tool, calc_tool],
llm=llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True, # הצג את תהליך החשיבה
max_iterations=5
)
# הרצה
result = agent.invoke({
"input": "כמה אוכלוסיית ישראל? חשב את הריבוע של המספר."
})
print(result["output"])
Custom Tool עם @tool Decorator
from langchain.tools import tool
from typing import Optional
@tool
def search_company_data(company_name: str) -> str:
"""
מחפש מידע על חברה ממסד הנתונים הפנימי.
קלט: שם החברה בעברית או אנגלית.
פלט: נתוני החברה כ-JSON.
"""
# כאן תיכנס הלוגיקה האמיתית שלך
companies_db = {
"אפל": {"מייסד": "Steve Jobs", "שנת ייסוד": 1976, "שווי": "3T$"},
"גוגל": {"מייסד": "Larry Page", "שנת ייסוד": 1998, "שווי": "2T$"}
}
return str(companies_db.get(company_name, "החברה לא נמצאה במסד הנתונים"))
@tool
def send_report_email(recipient: str, subject: str, body: str) -> str:
"""שולח דוח במייל. קלט: כתובת, נושא ותוכן."""
# כאן תיכנס לוגיקת שליחת המייל
print(f"שולח מייל ל-{recipient}")
return f"המייל נשלח בהצלחה ל-{recipient}"
# שימוש ב-Tool מותאם ב-Agent
agent_with_custom_tools = initialize_agent(
tools=[search_company_data, send_report_email],
llm=llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True
)
Modern Agent — LangGraph (מומלץ לפרודקשיין)
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langgraph.prebuilt import create_react_agent
llm = ChatOpenAI(model="gpt-4o")
tools = [wikipedia_tool, search_tool, calc_tool]
# create_react_agent מ-LangGraph — הדרך המודרנית
agent = create_react_agent(llm, tools)
# הרצה
result = agent.invoke({
"messages": [HumanMessage(content="מה מזג האוויר בתל אביב היום?")]
})
print(result["messages"][-1].content)
לאפליקציות פרודקשיין עם Agents מורכבים, LangGraph (חלק מהמשפחה של LangChain) מציע שליטה טובה יותר על ה-State Management, לולאות, ו-Human-in-the-loop. התקנה: pip install langgraph.
LangSmith — Monitoring ו-Debugging
LangSmith הוא פלטפורמת ה-Observability הרשמית של LangChain. הוא מאפשר לעקוב אחרי כל קריאה ל-LLM, לנפות באגים, למדוד Latency ועלויות, ולנהל ניסויים. חיוני לכל אפליקציה שעוברת לפרודקשיין.
הגדרת LangSmith Tracing
# .env — הוסף את המשתנים האלה
LANGCHAIN_TRACING_V2=true
LANGCHAIN_ENDPOINT=https://api.smith.langchain.com
LANGCHAIN_API_KEY=ls__your_key_here
LANGCHAIN_PROJECT=my-production-app
import os
from dotenv import load_dotenv
load_dotenv()
# אין צורך בשינוי קוד נוסף — Tracing פועל אוטומטית!
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser
llm = ChatOpenAI(model="gpt-4o")
prompt = ChatPromptTemplate.from_template("ענה בעברית: {question}")
chain = prompt | llm | StrOutputParser()
# כל הרצה מועברת אוטומטית ל-LangSmith Dashboard
result = chain.invoke({"question": "מהי LangChain?"})
print(result)
מה LangSmith מציג?
- Trace View: ציר זמן ויזואלי של כל שלב ב-Chain — Prompt, LLM Call, Output Parser
- Token Usage: כמה Tokens נצרכו ובאיזה עלות — לכל קריאה ובצבירה
- Latency: זמן תגובה לכל שלב — עוזר לזהות צווארי בקבוק
- Error Tracking: לכידת שגיאות עם הקשר מלא ללא צורך בלוגים נוספים
- Playground: שחזור הרצה ספציפית ועריכת ה-Prompt ישירות בדשבורד
- Datasets: בניית מאגר Test Cases להשוואת גרסאות
LangSmith Evaluation — בדיקת איכות
from langsmith.evaluation import evaluate, LangChainStringEvaluator
# הגדרת Evaluator להשוואת תשובות
evaluator = LangChainStringEvaluator("qa", config={"llm": ChatOpenAI(model="gpt-4o")})
# הרצת Evaluation על Dataset שיצרת ב-LangSmith
results = evaluate(
lambda inputs: chain.invoke(inputs),
data="my-test-dataset",
evaluators=[evaluator],
experiment_prefix="v1.2-test"
)
print(results.to_pandas())
5 טיפים מתקדמים
טיפ 1 — Streaming לחוויית משתמש טובה יותר
במקום לחכות שהמודל יסיים את התשובה המלאה, Streaming מאפשר להציג את הטקסט תוך כדי יצירתו. זה משפר דרמטית את חוויית המשתמש באפליקציות צ'אט.
import asyncio
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser
llm = ChatOpenAI(model="gpt-4o", streaming=True)
chain = ChatPromptTemplate.from_template("הסבר: {topic}") | llm | StrOutputParser()
# סטרימינג סינכרוני
for chunk in chain.stream({"topic": "LangChain"}):
print(chunk, end="", flush=True)
# סטרימינג אסינכרוני (לשימוש ב-FastAPI / Async frameworks)
async def stream_response():
async for chunk in chain.astream({"topic": "LangChain"}):
print(chunk, end="", flush=True)
asyncio.run(stream_response())
טיפ 2 — Caching להפחתת עלויות
LangChain כולל מנגנון Cache שמונע קריאות כפולות ל-API. אם אותה שאלה נשאלת שוב, התשובה מוחזרת מהמטמון ללא עלות.
from langchain.globals import set_llm_cache
from langchain.cache import InMemoryCache, SQLiteCache
# Cache בזיכרון — נמחק עם כיבוי התוכנה
set_llm_cache(InMemoryCache())
# Cache בקובץ SQLite — נשמר בין הפעלות
set_llm_cache(SQLiteCache(database_path=".langchain.db"))
# עכשיו כל Chain ישתמש ב-Cache אוטומטית
llm = ChatOpenAI(model="gpt-4o")
# הקריאה הראשונה → קריאה ל-API
result1 = llm.invoke("מה בירת ישראל?")
# הקריאה השנייה → מוחזר מה-Cache, ללא עלות!
result2 = llm.invoke("מה בירת ישראל?")
טיפ 3 — Fallback למודלים חלופיים
בפרודקשיין, חשוב להגדיר Fallback — אם המודל הראשי לא זמין, המערכת עוברת אוטומטית למודל חלופי.
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
# מודל ראשי: GPT-4o
primary_llm = ChatOpenAI(model="gpt-4o")
# מודל גיבוי: Claude
fallback_llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
# שרשרת Fallback אוטומטית
llm_with_fallback = primary_llm.with_fallbacks([fallback_llm])
# אם GPT-4o יחזיר שגיאה, Claude יופעל אוטומטית
result = llm_with_fallback.invoke("שאלה חשובה")
טיפ 4 — Structured Output עם Pydantic
במקום לפרסר טקסט חופשי, ניתן להגדיר Schema ל-Pydantic ו-LangChain יוודא שהמודל מחזיר JSON תקין בדיוק לפי המבנה.
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
from typing import List
class ProductReview(BaseModel):
rating: int = Field(description="דירוג מ-1 עד 5", ge=1, le=5)
pros: List[str] = Field(description="יתרונות המוצר")
cons: List[str] = Field(description="חסרונות המוצר")
summary: str = Field(description="סיכום קצר בעברית")
llm = ChatOpenAI(model="gpt-4o")
structured_llm = llm.with_structured_output(ProductReview)
review = structured_llm.invoke(
"נתח את הביקורת: המוצר טוב אבל יקר מדי ואיטי בהפעלה"
)
print(f"דירוג: {review.rating}/5")
print(f"יתרונות: {review.pros}")
print(f"חסרונות: {review.cons}")
טיפ 5 — Conversational Memory לצ'אטבוטים
בניית צ'אטבוט שזוכר את ההיסטוריה של השיחה — כולל ניהול חלון Context לחיסכון ב-Tokens.
from langchain_openai import ChatOpenAI
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
llm = ChatOpenAI(model="gpt-4o")
prompt = ChatPromptTemplate.from_messages([
("system", "אתה עוזר AI ידידותי. ענה תמיד בעברית."),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
chain = prompt | llm
# ניהול זיכרון לפי session_id
store = {}
def get_session_history(session_id: str) -> InMemoryChatMessageHistory:
if session_id not in store:
store[session_id] = InMemoryChatMessageHistory()
return store[session_id]
chatbot = RunnableWithMessageHistory(
chain,
get_session_history,
input_messages_key="input",
history_messages_key="history"
)
# שיחה עם זיכרון
config = {"configurable": {"session_id": "user_123"}}
r1 = chatbot.invoke({"input": "שמי דוד"}, config=config)
r2 = chatbot.invoke({"input": "מה שמי?"}, config=config)
# r2 יענה "שמך דוד" — הוא זוכר!
מודלים — ChatOpenAI, ChatAnthropic, Gemini
LangChain עוטף את כל ספקי ה-LLM בממשק אחיד. ניתן להחליף בין מודלים בשינוי שורה אחת בלבד — יתרון עצום לבדיקות ולגמישות.
השוואת ספקים
from langchain_anthropic import ChatAnthropic
from langchain_openai import ChatOpenAI
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_community.llms import Ollama # מודל מקומי
# Anthropic Claude
claude = ChatAnthropic(
model="claude-3-5-sonnet-20241022",
temperature=0.3,
max_tokens=4096
)
# OpenAI GPT-4o
gpt4o = ChatOpenAI(
model="gpt-4o",
temperature=0.3
)
# Google Gemini
gemini = ChatGoogleGenerativeAI(
model="gemini-2.0-flash",
temperature=0.3
)
# Ollama — מודל לוקאלי (ב-Llama 3.1, Mistral וכדומה)
local_llm = Ollama(model="llama3.1")
# ממשק זהה לכולם!
for llm, name in [(claude, "Claude"), (gpt4o, "GPT-4o"), (gemini, "Gemini")]:
response = llm.invoke("מה בירת ישראל? ענה במשפט אחד.")
print(f"{name}: {response.content}")
RAG מתקדם — Re-ranking ו-Hybrid Search
RAG בסיסי (Vector Search + Context Injection) עובד טוב אבל לא מושלם. RAG מתקדם משלב מספר טכניקות לשיפור דרמטי של הדיוק.
Multi-Query Retrieval
במקום לשלוח שאלה אחת ל-Vector Store, Multi-Query יוצר 3-5 ניסוחים שונים של השאלה ומחפש עם כולם. מגדיל משמעותית את ה-Recall.
from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
# Vector Store קיים
embeddings = OpenAIEmbeddings()
vectorstore = Chroma(embedding_function=embeddings, persist_directory="./db")
base_retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# Multi-Query Retriever — יוצר 5 ניסוחים שונים אוטומטית
multi_retriever = MultiQueryRetriever.from_llm(
retriever=base_retriever,
llm=llm,
prompt=PromptTemplate(
template="""Generate 5 different versions of this question in Hebrew and English:
Question: {question}
Output (5 lines, one per question):""",
input_variables=["question"]
)
)
# השימוש זהה לכל Retriever אחר
docs = multi_retriever.get_relevant_documents("מה המדיניות של החברה לגבי חופשות?")
Hybrid Search — BM25 + Vector
Hybrid Search משלב חיפוש מבוסס מילות מפתח (BM25) עם חיפוש סמנטי (Vector). מצוין כשיש תוצאות שתלויות במונחים ספציפיים (שמות, מספרים, מותגים).
from langchain_community.retrievers import BM25Retriever
from langchain.retrievers import EnsembleRetriever
# BM25 Retriever — חיפוש מבוסס מילות מפתח
bm25_retriever = BM25Retriever.from_documents(docs)
bm25_retriever.k = 4
# Vector Retriever — חיפוש סמנטי
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
# Hybrid — 50% מילות מפתח, 50% סמנטי
hybrid_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.5, 0.5]
)
# RAG Chain עם Hybrid Search
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
rag_prompt = ChatPromptTemplate.from_template("""ענה בעברית על בסיס ההקשר הבא בלבד.
אם אין תשובה בהקשר, אמור "אין מידע מספיק".
הקשר:
{context}
שאלה: {question}
""")
llm = ChatOpenAI(model="gpt-4o")
# Full RAG Chain עם Hybrid Search
hybrid_rag = (
{"context": hybrid_retriever | (lambda docs: "\n\n".join(d.page_content for d in docs)),
"question": RunnablePassthrough()}
| rag_prompt
| llm
| StrOutputParser()
)
answer = hybrid_rag.invoke("מה המדיניות של החברה לגבי עובדי Remote?")
5 פרויקטים מעשיים
מ-Q&A פשוט ועד מערכת Customer Support מלאה — הנה חמישה פרויקטים שתוכל לבנות עם LangChain.
שאלות ותשובות על מסמך אחד (PDF / TXT). RAG בסיסי עם FAISS.
מחלץ מידע מובנה (תאריכים, צדדים, תנאים) מחוזים משפטיים. מחזיר JSON.
RAG על עשרות מסמכים, Notion, Confluence ו-Google Drive בו-זמנית.
Agent שעונה על שאלות לקוחות, פותח Tickets ב-Zendesk, ומסלם לאדם כשצריך.
Graph מלא: Plan → Research → Critique → Refine → Publish. Human approval לפני פרסום.
גיליון עזר — Component Reference
Document Loaders — מקורות נתונים
| מקור | Loader | התקנה |
|---|---|---|
| PyPDFLoader | pip install pypdf | |
| Word | Docx2txtLoader | pip install docx2txt |
| Web Page | WebBaseLoader | pip install beautifulsoup4 |
| CSV | CSVLoader | מובנה ב-langchain |
| Notion | NotionDBLoader | pip install notion-client |
| YouTube | YoutubeLoader | pip install youtube-transcript-api |
Vector Stores — השוואה
| Vector Store | מתאים ל | מחיר |
|---|---|---|
| FAISS | Prototyping, קבצים קטנים, אין Server | חינם (לוקאלי) |
| Chroma | פרויקטים בינוניים, פשוט לפריסה | חינם (self-hosted) |
| Pinecone | פרודקשיין, מיליוני מסמכים, Scale | Serverless חינם עד 2GB |
| Weaviate | Hybrid Search מובנה, Multi-tenancy | Cloud / Self-hosted |
שגיאות נפוצות ופתרונות
from tenacity import retry, wait_exponential ועטוף את ה-LLM calls.chunk_size ל-500 ואת k ל-3 ב-Retriever.k.סיכום — LangChain vs LlamaIndex vs Direct API
| קריטריון | LangChain | LlamaIndex | Direct API |
|---|---|---|---|
| מורכבות | בינונית | בינונית | נמוכה 🏆 |
| RAG | מעולה 🏆 | מעולה 🏆 | ידנית |
| Agents | מעולה 🏆 | טוב | ידנית |
| קהילה | ענקית 🏆 | גדולה | קטנה |
| ביצועים | טוב | טוב | מהיר 🏆 |
| תמיכת מודלים | רחבה ביותר 🏆 | רחבה | ספציפית |
| Monitoring | LangSmith 🏆 | LlamaTrace | ידנית |
מסקנה: LangChain הוא הבחירה הנכונה לרוב הפרויקטים — במיוחד כשצריך Agents מורכבים, חיבור למגוון מודלים, ו-Monitoring בפרודקשיין. LlamaIndex עדיף כשה-Use Case הוא RAG בלבד על מסמכים מורכבים. Direct API מתאים לפרויקטים קטנים שמשתמשים במודל אחד ורוצים שליטה מלאה.
קישורים שימושיים
- תיעוד רשמי: python.langchain.com/docs/get_started
- LangSmith: smith.langchain.com — ניטור ו-Evaluation
- LangGraph: langchain-ai.github.io/langgraph — Agents מורכבים
- GitHub: github.com/langchain-ai/langchain — קוד מקור ו-Issues
- LangChain Hub: smith.langchain.com/hub — ספרייה של Prompts מוכנים
- Discord: discord.gg/langchain — קהילה פעילה לשאלות
הצעד הבא
אחרי שמבינים LangChain — המעמיק הטבעי הוא ללמוד RAG לעומק: כיצד לבנות מערכות Retrieval מתקדמות עם Re-ranking, Hybrid Search ו-Multi-vector Retrieval. הצעד הבא הוא גם LangGraph לבניית Agents מורכבים עם State Management.