الدرس 10 من 22

بناء التطبيقات مع Ollama

LangChain مع Ollama

3 دقيقة للقراءة

LangChain يوفر تجريدات عالية المستوى لبناء تطبيقات نماذج اللغة الكبيرة. حزمة langchain-ollama تقدم تكامل نماذج محلية سلس.

التثبيت

# ثبّت تكامل Ollama الرسمي (ليس langchain-community)
pip install langchain-ollama langchain

نموذج الدردشة الأساسي

from langchain_ollama import ChatOllama

# هيئ نموذج الدردشة
llm = ChatOllama(
    model="llama3.2",
    temperature=0.7
)

# استدعاء بسيط
response = llm.invoke("What is the meaning of life?")
print(response.content)

استخدام أنواع الرسائل

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

llm = ChatOllama(model="llama3.2")

messages = [
    SystemMessage(content="You are a helpful Python tutor."),
    HumanMessage(content="What's a decorator?"),
]

response = llm.invoke(messages)
print(response.content)

# استمر في المحادثة
messages.append(response)  # أضف رد AI
messages.append(HumanMessage(content="Can you show me an example?"))
response2 = llm.invoke(messages)
print(response2.content)

تدفق الردود

from langchain_ollama import ChatOllama

llm = ChatOllama(model="llama3.2")

# تدفق الرموز
for chunk in llm.stream("Explain recursion step by step"):
    print(chunk.content, end="", flush=True)
print()

قوالب الطلبات

from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate

llm = ChatOllama(model="llama3.2")

# أنشئ قالب طلب قابل لإعادة الاستخدام
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a {role}. Be concise and helpful."),
    ("human", "{question}")
])

# أنشئ السلسلة
chain = prompt | llm

# استخدم السلسلة
response = chain.invoke({
    "role": "senior Python developer",
    "question": "What's the difference between a list and a tuple?"
})
print(response.content)

التضمينات

from langchain_ollama import OllamaEmbeddings

# هيئ التضمينات
embeddings = OllamaEmbeddings(model="llama3.2")

# نص واحد
vector = embeddings.embed_query("What is machine learning?")
print(f"بُعد التضمين: {len(vector)}")

# نصوص متعددة
texts = ["Python programming", "JavaScript development", "AI research"]
vectors = embeddings.embed_documents(texts)
print(f"ولّدت {len(vectors)} تضمينات")

بناء سلسلة RAG بسيطة

from langchain_ollama import ChatOllama, OllamaEmbeddings
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

# المكونات
llm = ChatOllama(model="llama3.2")
embeddings = OllamaEmbeddings(model="llama3.2")

# مخزن مستندات بسيط في الذاكرة (للعرض)
documents = [
    "Python was created by Guido van Rossum in 1991.",
    "Python emphasizes code readability and simplicity.",
    "Python supports multiple programming paradigms."
]

# ضمّن المستندات
doc_embeddings = embeddings.embed_documents(documents)

def simple_retriever(query: str) -> str:
    """جد المستند الأكثر صلة باستخدام تشابه جيب التمام."""
    import numpy as np

    query_embedding = embeddings.embed_query(query)

    similarities = [
        np.dot(query_embedding, doc_emb) /
        (np.linalg.norm(query_embedding) * np.linalg.norm(doc_emb))
        for doc_emb in doc_embeddings
    ]

    best_idx = np.argmax(similarities)
    return documents[best_idx]

# طلب RAG
prompt = ChatPromptTemplate.from_template("""
Answer the question based only on the following context:

Context: {context}

Question: {question}

Answer:""")

# ابنِ السلسلة
rag_chain = (
    {"context": lambda x: simple_retriever(x), "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

# استخدم السلسلة
answer = rag_chain.invoke("Who created Python?")
print(answer)

تحليل المخرجات

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

class CodeReview(BaseModel):
    """مخرجات مراجعة كود منظمة."""
    issues: list[str] = Field(description="قائمة المشاكل المكتشفة")
    suggestions: list[str] = Field(description="اقتراحات التحسين")
    score: int = Field(description="درجة جودة الكود 1-10")

llm = ChatOllama(model="llama3.2", format="json")

prompt = ChatPromptTemplate.from_messages([
    ("system", "Review the code and respond in JSON with: issues, suggestions, score (1-10)"),
    ("human", "Review this code:\n```python\n{code}\n```")
])

chain = prompt | llm | JsonOutputParser()

code = """
def calc(x):
    return x*2+1
"""

review = chain.invoke({"code": code})
print(f"الدرجة: {review['score']}/10")
print(f"المشاكل: {review['issues']}")

تكوين خيارات Ollama

from langchain_ollama import ChatOllama

# تكوين كامل
llm = ChatOllama(
    model="llama3.2",
    temperature=0.8,
    num_ctx=4096,         # نافذة السياق
    num_predict=256,      # أقصى رموز
    top_k=40,
    top_p=0.9,
    repeat_penalty=1.1,
    stop=["Human:", "User:"],  # تسلسلات الإيقاف
    base_url="http://localhost:11434"  # نقطة نهاية مخصصة
)

المعالجة الدفعية

from langchain_ollama import ChatOllama

llm = ChatOllama(model="llama3.2")

# عالج طلبات متعددة
prompts = [
    "What is Python?",
    "What is JavaScript?",
    "What is Rust?"
]

# استدعاء دفعي
responses = llm.batch(prompts)

for prompt, response in zip(prompts, responses):
    print(f"س: {prompt}")
    print(f"ج: {response.content[:100]}...")
    print()

تخزين الردود مؤقتاً

from langchain_ollama import ChatOllama
from langchain.cache import InMemoryCache
from langchain.globals import set_llm_cache

# فعّل التخزين المؤقت
set_llm_cache(InMemoryCache())

llm = ChatOllama(model="llama3.2")

# الاستدعاء الأول - يصل للنموذج
response1 = llm.invoke("What is 2+2?")

# الاستدعاء الثاني - يُرجع النتيجة المخزنة فوراً
response2 = llm.invoke("What is 2+2?")

النقاط الرئيسية

الميزة فئة LangChain
نموذج الدردشة ChatOllama
التضمينات OllamaEmbeddings
الحزمة langchain-ollama
التنسيق format="json" لمخرجات JSON

LangChain يجرد تعقيد بناء تطبيقات نماذج اللغة الكبيرة. في الدرس التالي، سنستخدم LangGraph لسير عمل متعدد الخطوات والحالات. :::

اختبار

الوحدة 3: بناء التطبيقات مع Ollama

خذ الاختبار