Ollama: تكامل LangChain

LangChain هو مايسترو تنسيق تطبيقات الذكاء الاصطناعي — النماذج هي الممثلون، والسلاسل هي النصوص، والوكلاء هم المخرجون.

💡 نصيحة: جوهر LangChain هو البنية ثلاثية الطبقات وكيل/سلسلة/أداة — السلسلة هي خط أنابيب ثابت (موجه→نموذج لغوي كبير→محلل)، والأداة هي قدرة خارجية قابلة للاستدعاء (الاستعلام عن قاعدة بيانات، البحث في المستندات)، والوكيل هو صانع قرار مستقل يختار ديناميكيًا أي أدوات يستدعيها. 90% من السيناريوهات تخدمها السلاسل جيدًا؛ استخدم الوكلاء فقط عند الحاجة إلى اتخاذ القرارات الديناميكية.

📋 المتطلبات المسبقة: يجب أن تتقن أولاً ما يلي

1. ما ستتعلمه


2. قصة حقيقية من مدير تقنية شركة ناشئة

(1) المشكلة: التحليل اليدوي لـ 50 تقرير مؤشرات كل شهر

تتابع شركة Alice SaaS 50 مؤشرًا تجاريًا، وتتطلب تحليل الاتجاهات وكتابة التقارير يدويًا كل شهر. يقضي أحد المحللين 3 أيام لإكمال العمل، وغالبًا ما تُفقد إشارات الشذوذ المهمة.

(2) الحل: وكيل LangChain للتحليل الآلي

استخدام LangChain + Ollama لبناء وكيل ذكاء اصطناعي يقرأ بيانات المؤشرات تلقائيًا ويحدد الشذوذ ويُنشئ تقارير التحليل:

PYTHON
from langchain_ollama import ChatOllama

llm = ChatOllama(model="qwen2.5", temperature=0.2)
result = llm.invoke("Analyze the 20% drop in MRR last month")

3. اتصال LangChain + Ollama

💡 نصيحة: المعامل base_url في ChatOllama يكون افتراضيًا http://localhost:11434. إذا كان Ollama مُنشرًا على مضيف آخر أو في حاوية دوكر، يجب تعيين base_url="http://ollama:11434" أو العنوان المقابل صراحةً.

(1) التثبيت والتهيئة

BASH
pip install langchain langchain-ollama langchain-community

(2) مكونان أساسيان

المكون الصنف الغرض
نموذج المحادثة ChatOllama توليد المحادثات
التضمينات OllamaEmbeddings تحويل النص إلى متجهات
100%
flowchart TD
    A[تطبيق LangChain] --> B[ChatOllama<br/>qwen2.5 / llama3.2]
    A --> C[OllamaEmbeddings<br/>nomic-embed-text]
    B --> D[خادم Ollama<br/>localhost:11434]
    C --> D
معامل ChatOllama النوع الافتراضي الوصف
model str اسم النموذج
temperature float 0.8 العشوائية
base_url str http://localhost:11434 عنوان الخادم
num_ctx int 2048 نافذة السياق

(1) ▶ مثال: استدعاء ChatOllama الأساسي

PYTHON
from langchain_ollama import ChatOllama
from langchain_core.messages import HumanMessage, SystemMessage

# Initialize ChatOllama
llm = ChatOllama(model="qwen2.5", temperature=0.3)

# Simple invocation
response = llm.invoke("What is RAG?")
print(response.content)

# With system message
response = llm.invoke([
    SystemMessage(content="You are a data analyst. Be concise."),
    HumanMessage(content="What causes MRR to drop?")
])
print(response.content)

الإخراج:

TEXT
# Execution successful

4. قالب الموجه + سلسلة

(1) هندسة الموجهات المترابطة

تجعل قوالب الموجهات الموجهات قابلة للمعاملات وقابلة لإعادة الاستخدام وقابلة للتكوين:

100%
flowchart LR
    A[متغيرات الإدخال] --> B[قالب الموجه]
    B --> C[ChatOllama]
    C --> D[محلل الإخراج]
    D --> E[نتيجة منظمة]
نوع السلسلة الوصف حالة الاستخدام
LLMChain موجه → نموذج لغوي كبير → إخراج استنتاج خطوة واحدة
SequentialChain سلاسل متعددة بالتسلسل تحليل متعدد الخطوات
RouterChain توجيه بناءً على الإدخال معالجة التفرع

(2) ▶ مثال: قالب الموجه + سلسلة

PYTHON
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

llm = ChatOllama(model="qwen2.5", temperature=0.3)

# Define prompt template
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a {role}. Be concise and professional."),
    ("human", "{input}")
])

# Build chain: prompt -> llm -> parser
chain = prompt | llm | StrOutputParser()

# Invoke with variables
result = chain.invoke({
    "role": "customer service agent for e-commerce",
    "input": "Customer wants to cancel order #12345"
})
print(result)

الإخراج:

TEXT
# Execution successful

5. محلل الإخراج للإخراج المنظم

⚠️ تحذير: النماذج الصغيرة (أقل من 3 مليارات معامل) تُنشئ هياكل JSON غير مستقرة، مما يتسبب في فشل تحليل PydanticOutputParser. استخدم نموذج 8 مليارات+ مع format="json"، وأضف منطق إعادة المحاولة try/except في الكود.

(1) محللات الإخراج الشائعة

المحلل الغرض تنسيق الإخراج
StrOutputParser نص عادي سلسلة
JsonOutputParser كائن JSON قاموس
PydanticOutputParser نموذج Pydantic كائن منظم
CommaSeparatedListOutputParser قائمة مفصولة بفواصل list[str]

(2) مقارنة الإخراج المنظم بـ Pydantic

الطريقة المزايا العيوب
format=json بسيط بدون التحقق من النوع
JsonOutputParser لديه تلميحات المخطط التحليل قد يفشل
PydanticOutputParser تحقق كامل من النوع يعتمد على التزام النموذج بالمخطط

(3) ▶ مثال: الإخراج المنظم بـ Pydantic

PYTHON
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field

# Define output schema
class CustomerIntent(BaseModel):
    intent: str = Field(description="Customer intent category")
    confidence: float = Field(description="Confidence score 0-1")
    order_number: str | None = Field(description="Order number if mentioned")

# Create parser
parser = PydanticOutputParser(pydantic_object=CustomerIntent)

# Build chain with format instructions
llm = ChatOllama(model="qwen2.5", temperature=0.1, format="json")
prompt = ChatPromptTemplate.from_messages([
    ("system", "Classify the customer intent.\n{format_instructions}"),
    ("human", "{query}")
])

chain = prompt | llm | parser

# Invoke
result = chain.invoke({
    "query": "I want to track my order #88765",
    "format_instructions": parser.get_format_instructions()
})
print(f"Intent: {result.intent}")
print(f"Confidence: {result.confidence}")
print(f"Order: {result.order_number}")

الإخراج:

TEXT
# Execution successful

6. وكيل استدعاء الأدوات

⚠️ ملاحظة: قد ينتج الوكلاء إخراجًا غير مستقر — يمكن أن تؤدي حلقات استنتاج النماذج المحلية إلى "حلقات لا نهائية" (استدعاء نفس الأداة بشكل متكرر) أو "استدعاءات أدوات وهمية" (استدعاء أدوات غير موجودة). عيّن دائمًا max_iterations=3-5 لتحديد عدد الحلقات، واستخدم temperature=0 لزيادة الحتمية. النماذج ذات 3 مليارات لديها قدرات وكيل محدودة؛ يُوصى بـ 8 مليارات+.

💡 نصيحة: قدرة استدعاء الدوال Function Calling في النماذج المحلية لـ Ollama ليست مستقرة مثل GPT-4. يُوصى باستخدام نمط وكيل ReAct + مزين @tool بدلاً من استدعاء الدوال الأصلي لتحقيق توافق أفضل، ويمكن لـ temperature=0 تحسين حتمية استدعاء الأدوات.

(1) بنية الوكيل

100%
flowchart TD
    A[إدخال المستخدم] --> B[الوكيل]
    B --> C{هل يحتاج أداة؟}
    C -->|نعم| D[استدعاء أداة]
    D --> E[نتيجة الأداة]
    E --> B
    C -->|لا| F[الإجابة النهائية]
نوع الوكيل الوصف حالة الاستخدام
وكيل ReAct حلقة استنتاج + إجراء مهام معقدة تتطلب استدعاء أدوات
محادثة منظمة استدعاء أدوات منظمة أدوات متعددة، معاملات متعددة
دوال OpenAI وضع استدعاء الدوال مدعوم جزئيًا من Ollama

(2) أنماط تعريف الأدوات

طريقة التعريف الوصف مثال
مزين @tool أداة بسيطة @tool def func(...)
StructuredTool أداة مع وصف StructuredTool.from_function(...)
Pydantic + BaseTool أداة منشأة بقوة class MyTool(BaseTool)

(4) ▶ مثال: وكيل ReAct في الممارسة

PYTHON
from langchain_ollama import ChatOllama
from langchain_core.tools import tool
from langchain.agents import AgentExecutor, create_react_agent
from langchain_core.prompts import PromptTemplate

# Define tools
@tool
def get_order_status(order_id: str) -> str:
    """Get the status of an order by its ID."""
    # Simulated database lookup
    orders = {
        "12345": "Shipped, arriving in 2 days",
        "88765": "Processing, shipping tomorrow",
        "99999": "Delivered on 2024-01-15"
    }
    return orders.get(order_id, f"Order {order_id} not found")

@tool
def check_product_stock(product_name: str) -> str:
    """Check if a product is in stock."""
    stock = {
        "wireless headphones": "In stock: 45 units",
        "laptop stand": "Out of stock, restock in 3 days",
        "usb cable": "In stock: 200 units"
    }
    return stock.get(product_name.lower(), f"Product '{product_name}' not found")

# Build agent
llm = ChatOllama(model="qwen2.5", temperature=0)
tools = [get_order_status, check_product_stock]

prompt = PromptTemplate.from_template(
    """Answer the following question. You have access to these tools:
{tools}

Use this format:
Question: the input question
Thought: what to do
Action: tool name (one of [{tool_names}])
Action Input: tool input
Observation: tool output
... (repeat Thought/Action/Action Input/Observation)
Thought: I know the final answer
Final Answer: the final answer

Question: {input}
{agent_scratchpad}"""
)

agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# Run agent
result = agent_executor.invoke({
    "input": "What is the status of order 88765?"
})
print(result["output"])

الإخراج:

TEXT
# Function defined successfully

7. مثال شامل: وكيل تحليل مقاييس SaaS الخاص بـ Alice

ℹ️ معلومة: القيمة الافتراضية لـ max_iterations في AgentExecutor الخاص بـ LangChain هي 15، لكن النماذج المحلية تستنتج ببطء أكبر. تعيينها إلى 3-5 يمنع الحلقات اللانهائية. أيضًا عيّن verbose=True لمراقبة عملية استنتاج الوكيل.

PYTHON
# ============================================
# Comprehensive: SaaS metrics analysis agent
# Uses LangChain + Ollama for automated analysis
# ============================================

from langchain_ollama import ChatOllama
from langchain_core.tools import tool
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.agents import AgentExecutor, create_react_agent
from langchain_core.prompts import PromptTemplate
import json

# Simulated metrics database
METRICS_DB = {
    "mrr": {"current": 85000, "previous": 106250, "change": -20},
    "churn_rate": {"current": 8.5, "previous": 5.2, "change": 63},
    "arr": {"current": 1020000, "previous": 1275000, "change": -20},
    "active_users": {"current": 12500, "previous": 11800, "change": 6},
    "cac": {"current": 250, "previous": 180, "change": 39},
    "ltv": {"current": 2400, "previous": 3200, "change": -25}
}

@tool
def get_metric(metric_name: str) -> str:
    """Get a SaaS metric value. Available: mrr, churn_rate, arr, active_users, cac, ltv."""
    data = METRICS_DB.get(metric_name.lower())
    if data:
        return json.dumps(data)
    return f"Metric '{metric_name}' not found. Available: {list(METRICS_DB.keys())}"

@tool
def compare_metrics(metric1: str, metric2: str) -> str:
    """Compare two metrics and identify correlations."""
    m1 = METRICS_DB.get(metric1.lower())
    m2 = METRICS_DB.get(metric2.lower())
    if not m1 or not m2:
        return "One or both metrics not found."
    return json.dumps({
        "metric1": {"name": metric1, **m1},
        "metric2": {"name": metric2, **m2},
        "correlation_note": "Both metrics show negative trends"
    })

# Build analysis agent
llm = ChatOllama(model="qwen2.5", temperature=0.2)
tools = [get_metric, compare_metrics]

prompt = PromptTemplate.from_template(
    """You are a SaaS metrics analyst. Analyze data and provide insights.
Available tools: {tools}

Format:
Question: the input
Thought: what to do
Action: tool name from [{tool_names}]
Action Input: tool input
Observation: tool output
... (repeat as needed)
Thought: I have enough information
Final Answer: detailed analysis with actionable recommendations

Question: {input}
{agent_scratchpad}"""
)

agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True, max_iterations=5)

# Run analysis
if __name__ == "__main__":
    result = executor.invoke({
        "input": "MRR dropped 20% last month. Analyze the key metrics and identify likely causes with recommendations."
    })
    print("\n=== Analysis Report ===")
    print(result["output"])

❓ أسئلة شائعة

س ما الفرق بين langchain-ollama وlangchain-community؟
ج langchain-ollama هو حزمة تكامل Ollama الرسمية، وتحتوي على ChatOllama وOllamaEmbeddings. langchain-community يتضمن أيضًا تكاملات قديمة، لكن يُوصى بالحزمة الرسمية.
س ماذا أفعل إذا كانت استدعاءات أدوات الوكيل غير مستقرة؟
ج اخفض temperature إلى 0، وتأكد من أن أوصاف الأدوات واضحة، واستخدم format=json لفرض الإخراج المنظم. النماذج الصغيرة (3 مليارات) لديها قدرات وكيل محدودة؛ يُوصى بـ 8 مليارات+.
س كيف أختار بين سلاسل LangChain والوكلاء؟
ج استخدم السلاسل لسير العمل الثابت (موجه → نموذج لغوي كبير → محلل)، والوكلاء لاتخاذ القرارات الديناميكية (اختيار الأدوات والخطوات بشكل مستقل). السلاسل تكفي لـ 90% من السيناريوهات.
س ماذا أفعل إذا فشل تحليل PydanticOutputParser؟
ج أضف format="json" لفرض إخراج JSON. أضف تعليمات تنسيق صريحة في الموجه. ارجع إلى JsonOutputParser عند الفشل.
س هل تدعم نماذج Ollama استدعاء الدوال Function Calling؟
ج جزئيًا. qwen2.5 وllama3.1 لديهما بعض قدرات Function Calling، لكنها ليست مستقرة مثل GPT-4. يُوصى باستخدام وكيل ReAct + مزين @tool كبديل.
س كيف يمكنني تصحيح أخطاء عملية استنتاج الوكيل؟
ج عيّن verbose=True لعرض حلقة Thought/Action/Observation للوكيل. يمكن لـ LangSmith (tracelangchain.com) تصور سلسلة التنفيذ الكاملة.

📖 ملخص


📝 تمارين

  1. أساسي (⭐): ابنِ سلسلة مع ChatOllama + قالب الموجه لتنفيذ تصنيف نية خدمة العملاء (الإخراج بتنسيق JSON).
  2. متوسط (⭐⭐): أنشئ وكيل ReAct مع أداتين (الاستعلام عن الطلب + التحقق من المخزون)، واختبر استدعاء الأدوات بـ 3 أسئلة مختلفة.
  3. متقدم (⭐⭐⭐): ابنِ وكيل تحليل مقاييس SaaS لـ Alice — يتضمن 4 أدوات على الأقل (الحصول على مؤشر، مقارنة المؤشرات، توليد وصف الرسم البياني، إرسال تنبيه)، مع إخراج تقرير تحليل منظم.
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%