TEHRAN
اتصال LangChain و LangGraph به OpenAI از ایران
← روزنامه‌نگاری۱۲ دقیقه مطالعه

اتصال LangChain و LangGraph به OpenAI از ایران

آموزش گام‌به‌گام اتصال LangChain و LangGraph به OpenAI از داخل ایران: ساخت RAG، tool agent، LangGraph حالت‌مند با کد Python آماده.

BYتیم 1xAi·منتشر: ۲۰۲۶/۰۵/۱۲ ۱۶:۲۲·بروزرسانی: ۲۰۲۶/۰۵/۱۳ ۰۹:۲۴·
LangChainAPIPythonآموزش
CONTENTS · در این مقاله (۲۱)
  1. مرور سریع: LangChain در برابر LangGraph
  2. پیش‌نیازها
  3. نصب پکیج‌ها
  4. گام ۱: ساده‌ترین chain ممکن
  5. گام ۲: ساخت یک سیستم RAG واقعی
  6. گام ۳: اولین Tool Agent با LangChain
  7. گام ۴: ورود به دنیای LangGraph
  8. مثال: agent برنامه‌ریز سفر
  9. گام ۵: Streaming برای UX بهتر
  10. گام ۶: Memory و persistence
  11. چند الگوی پیشرفته که در پروژه‌های واقعی استفاده می‌شوند
  12. ۱. Self-correcting RAG
  13. ۲. Multi-agent با LangGraph
  14. ۳. Human-in-the-loop
  15. ۴. Structured output
  16. عیب‌یابی: مشکلات رایج کاربر ایرانی
  17. خطای Connection Error
  18. خطای Authentication
  19. خطای ۴۲۹ Rate Limit
  20. کنترل هزینه در پروژه‌های LangChain
  21. جمع‌بندی

اگر در دنیای ساخت اپلیکیشن LLM فعال باشی، بدون شک با LangChain برخورد کرده‌ای. این فریم‌ورک پایتونی (که نسخهٔ JavaScript هم دارد) در دو سال گذشته به استاندارد دفاکتو برای ساخت RAG، agent، tool use و chainهای پیچیده تبدیل شده است. LangGraph، خواهر کوچک‌تر LangChain، به تو اجازه می‌دهد graphهای حالت‌مند بسازی — یعنی agentهایی که در طول مکالمه حافظه و وضعیت دارند. هر دو پروژه به‌طور پیش‌فرض به api.openai.com وصل می‌شوند که از ایران در دسترس نیست. خبر خوب: به‌خاطر پشتیبانی استاندارد LangChain از base_url، اتصال به یک پروکسی OpenAI-compatible مثل 1xAi دو خط کد بیشتر نیست. این مقاله گام‌به‌گام نشان می‌دهد چطور هم برای شروع، هم برای پروژه‌های production این کار را انجام دهی.

مرور سریع: LangChain در برابر LangGraph

LangChainLangGraph
تمرکز اصلیchain خطی، RAG، tool useworkflow حالت‌مند، multi-agent
ساختارزنجیره (chain) + LCELگراف جهت‌دار با node و edge
کنترل جریانمحدود به sequenceکامل (شرط، حلقه، parallel)
Stateمحدود (memory objects)first-class
کاربرد ایده‌آلچت ساده، خلاصه‌سازی، Q&Aagent پیچیده، human-in-the-loop

قاعدهٔ سرانگشتی: اگر workflow تو خطی است، LangChain کافی است. اگر نیاز داری branch بگیری، loop داشته باشی، یا در میانه از کاربر سؤال بپرسی، به LangGraph برو.

پیش‌نیازها

  • پایتون ۳.۹ یا بالاتر.
  • یک کلید 1xAi (یا هر پروکسی OpenAI-compatible دیگر). اگر هنوز نداری، در صفحهٔ ثبت‌نام چند دقیقه‌ای ساخته می‌شود.
  • حداقل ۱۰۰ هزار تومان شارژ.

اگر هنوز با مفهوم پروکسی API آشنا نیستی، اول مقالهٔ دسترسی به ChatGPT از داخل ایران را بخوان.

نصب پکیج‌ها

pip install langchain langchain-openai langgraph
pip install python-dotenv  # برای مدیریت متغیرها

یک فایل .env بساز:

OPENAI_API_KEY=1xai-xxxxxxxxxxxxxxxxxxxxxxxx
OPENAI_BASE_URL=https://1xai.ir/v1

نکتهٔ مهم: LangChain از این متغیرهای محیطی به‌صورت خودکار استفاده می‌کند. اما برای روشن بودن کد، توصیه می‌شود base_url را صریح در کد هم بدهی.

گام ۱: ساده‌ترین chain ممکن

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

load_dotenv()

llm = ChatOpenAI(
    model="gpt-5-mini",
    base_url="https://1xai.ir/v1",
    temperature=0.3
)

prompt = ChatPromptTemplate.from_messages([
    ("system", "تو دستیار خلاصه‌ساز فارسی هستی. متن را در ۲ جمله خلاصه کن."),
    ("user", "{text}")
])

chain = prompt | llm | StrOutputParser()

result = chain.invoke({
    "text": "متن طولانی فارسی شما اینجا..."
})
print(result)

چه اتفاقی افتاد؟ سه قطعه (prompt، llm، parser) با عملگر | به هم وصل شدند. این LCEL یا «LangChain Expression Language» است که جایگزین مدرن chainهای قدیمی شده.

گام ۲: ساخت یک سیستم RAG واقعی

RAG یعنی Retrieval-Augmented Generation: مدل به‌جای تکیه بر دانش داخلی خودش، اول از یک پایگاه دانش جست‌وجو می‌کند و بعد پاسخ می‌دهد. سناریو: یک ربات Q&A برای مستندات یک محصول.

from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

# 1. Load و split
docs = TextLoader("docs.txt", encoding="utf-8").load()
splitter = RecursiveCharacterTextSplitter(
    chunk_size=800,
    chunk_overlap=100
)
chunks = splitter.split_documents(docs)

# 2. Embedding با 1xAi
embeddings = OpenAIEmbeddings(
    model="text-embedding-3-small",
    base_url="https://1xai.ir/v1"
)

# 3. ساخت vector store
db = Chroma.from_documents(chunks, embeddings, persist_directory="./chroma_db")
retriever = db.as_retriever(search_kwargs={"k": 4})

# 4. Prompt RAG
template = """بر اساس context زیر به سؤال پاسخ بده. اگر پاسخ در context نیست، صادقانه بگو نمی‌دانی.

Context:
{context}

سؤال: {question}

پاسخ به فارسی:"""

prompt = ChatPromptTemplate.from_template(template)

# 5. مدل پاسخ
llm = ChatOpenAI(model="gpt-5-mini", base_url="https://1xai.ir/v1")

# 6. RAG chain
rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

print(rag_chain.invoke("چگونه می‌توانم پسوردم را تغییر دهم؟"))

این الگو در عمل قدرتمند است. برای تخمین هزینهٔ embedding و query، به مقالهٔ هزینهٔ ChatGPT API رجوع کن.

گام ۳: اولین Tool Agent با LangChain

Tool agent یعنی LLM که می‌تواند به صورت خودکار function call بزند. مثال: یک agent که می‌تواند آب‌وهوا چک کند و قیمت ارز بپرسد.

from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_core.tools import tool
from langchain_core.prompts import ChatPromptTemplate

@tool
def get_weather(city: str) -> str:
    """وضعیت آب‌وهوای شهر را برمی‌گرداند."""
    # اینجا فراخوانی API واقعی می‌رود
    return f"آب‌وهوای {city}: آفتابی، ۲۵ درجه"

@tool
def get_exchange_rate(currency: str) -> str:
    """قیمت ارز را به تومان برمی‌گرداند."""
    rates = {"USD": 60000, "EUR": 65000, "AED": 16500}
    return f"قیمت {currency}: {rates.get(currency, 'نامشخص')} تومان"

tools = [get_weather, get_exchange_rate]

llm = ChatOpenAI(
    model="gpt-5-mini",
    base_url="https://1xai.ir/v1"
)

prompt = ChatPromptTemplate.from_messages([
    ("system", "تو دستیار هستی. از ابزارها برای پاسخ استفاده کن."),
    ("user", "{input}"),
    ("placeholder", "{agent_scratchpad}")
])

agent = create_openai_tools_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

executor.invoke({
    "input": "هوای تهران چطوره؟ و قیمت دلار رو هم بگو."
})

وقتی این را اجرا می‌کنی، می‌بینی که agent خودش تصمیم می‌گیرد هر دو function را فراخوانی کند، نتیجه را ترکیب کند و یک پاسخ یکپارچه بدهد. این قدرت function calling در GPT است.

گام ۴: ورود به دنیای LangGraph

LangGraph وقتی شکوفا می‌شود که نیاز به state داری: مثلاً یک agent که چند مرحله را طی می‌کند، در میانه از کاربر تأیید می‌گیرد، و بر اساس پاسخ مسیرش را تغییر می‌دهد.

مثال: agent برنامه‌ریز سفر

from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END
from langgraph.graph.message import add_messages
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, AIMessage

class TravelState(TypedDict):
    messages: Annotated[list, add_messages]
    destination: str
    budget: int
    plan: str

llm = ChatOpenAI(
    model="gpt-5-mini",
    base_url="https://1xai.ir/v1"
)

def gather_requirements(state: TravelState) -> TravelState:
    response = llm.invoke([
        *state["messages"],
        HumanMessage(content="مقصد و بودجهٔ کاربر را از مکالمه استخراج کن. JSON با کلیدهای destination و budget برگردان.")
    ])
    # parse و ذخیره (ساده‌سازی شده)
    return {"messages": [response], "destination": "تهران", "budget": 10000000}

def create_plan(state: TravelState) -> TravelState:
    prompt = f"یک برنامهٔ سفر سه‌روزه به {state['destination']} با بودجهٔ {state['budget']} تومان بنویس."
    response = llm.invoke([HumanMessage(content=prompt)])
    return {"messages": [response], "plan": response.content}

def needs_more_info(state: TravelState) -> str:
    if not state.get("destination") or not state.get("budget"):
        return "gather"
    return "plan"

# ساخت گراف
workflow = StateGraph(TravelState)
workflow.add_node("gather", gather_requirements)
workflow.add_node("plan", create_plan)
workflow.set_entry_point("gather")
workflow.add_conditional_edges("gather", needs_more_info, {
    "gather": "gather",
    "plan": "plan"
})
workflow.add_edge("plan", END)

app = workflow.compile()
result = app.invoke({
    "messages": [HumanMessage(content="می‌خوام برم اصفهان، ۱۵ میلیون تومن دارم.")]
})

print(result["plan"])

این یک مثال ساده است، اما الگو را نشان می‌دهد: nodeها functionهایی هستند که state را تغییر می‌دهند، و edgeها مسیر بعدی را تعیین می‌کنند. می‌توانی شرط بگذاری، حلقه بسازی، یا چندین node را به‌صورت parallel اجرا کنی.

گام ۵: Streaming برای UX بهتر

اگر می‌خواهی پاسخ را token-به-token به کاربر نشان دهی (مثل خود ChatGPT)، LangChain به‌صورت native از streaming پشتیبانی می‌کند:

llm = ChatOpenAI(
    model="gpt-5-mini",
    base_url="https://1xai.ir/v1",
    streaming=True
)

for chunk in llm.stream([HumanMessage(content="یک شعر فارسی دربارهٔ تهران بگو.")]):
    print(chunk.content, end="", flush=True)

1xAi streaming را روی همهٔ مدل‌ها پشتیبانی می‌کند. اگر در محصول production هستی، streaming تأخیر perceived (یعنی آن‌چه کاربر حس می‌کند) را به‌شدت کاهش می‌دهد.

گام ۶: Memory و persistence

برای چت‌باتی که باید مکالمات قبلی را به‌خاطر بسپارد، ساده‌ترین راه استفاده از RunnableWithMessageHistory است:

from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

store = {}

def get_session_history(session_id: str):
    if session_id not in store:
        store[session_id] = InMemoryChatMessageHistory()
    return store[session_id]

chain_with_memory = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key="input",
    history_messages_key="history"
)

config = {"configurable": {"session_id": "user-123"}}

print(chain_with_memory.invoke(
    {"input": "اسم من علی است."},
    config=config
))

print(chain_with_memory.invoke(
    {"input": "اسم من چی بود؟"},
    config=config
))  # «اسم شما علی است»

برای production، InMemory را با Redis یا Postgres جایگزین کن. LangChain برای هر دو implementation آماده دارد.

چند الگوی پیشرفته که در پروژه‌های واقعی استفاده می‌شوند

۱. Self-correcting RAG

یک agent که اگر بازیابی اول نتیجهٔ کافی نداد، query را بازنویسی می‌کند و دوباره جست‌وجو می‌کند. در LangGraph به‌سادگی با یک loop قابل پیاده‌سازی است.

۲. Multi-agent با LangGraph

دو agent: یکی researcher که اطلاعات جمع می‌کند، یکی writer که محتوا می‌نویسد. supervisor agent تصمیم می‌گیرد کدام را فراخوانی کند. این الگو در ابزارهایی مثل CrewAI هم محبوب شده.

۳. Human-in-the-loop

LangGraph از interrupt پشتیبانی می‌کند: agent می‌تواند در میانهٔ کار صبر کند تا انسان تأیید بدهد. برای اپلیکیشن‌هایی که agent دارد ایمیل می‌فرستد یا پول خرج می‌کند حیاتی است.

۴. Structured output

برای گرفتن JSON ساختاریافته به‌جای متن آزاد:

from pydantic import BaseModel, Field

class Movie(BaseModel):
    title: str = Field(description="نام فیلم")
    year: int = Field(description="سال ساخت")
    rating: float = Field(description="امتیاز از ۱۰")

structured_llm = llm.with_structured_output(Movie)
result = structured_llm.invoke("اطلاعات فیلم Inception را بده.")
print(result.title, result.year, result.rating)

عیب‌یابی: مشکلات رایج کاربر ایرانی

خطای Connection Error

معمولاً به این معنا که base_url را تنظیم نکرده‌ای و LangChain دارد به api.openai.com می‌زند. چک کن متغیر محیطی OPENAI_BASE_URL و یا پارامتر base_url در ChatOpenAI درست تنظیم شده باشد.

خطای Authentication

کلید با 1xai- شروع شده؟ پشت سر آن فاصله نیست؟ از داشبورد کلید جدید بساز و امتحان کن.

خطای ۴۲۹ Rate Limit

تعداد درخواست همزمان از سقف عبور کرده. در 1xAi می‌توانی از فرم تماس سقف را افزایش دهی. در کد هم می‌توانی از RetryPolicy استفاده کنی:

from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(3), wait=wait_exponential(min=1, max=10))
def safe_invoke(query: str) -> str:
    return chain.invoke(query)

کنترل هزینه در پروژه‌های LangChain

LangChain یک callback آماده به نام get_openai_callback دارد که مصرف توکن و هزینهٔ تخمینی را گزارش می‌دهد:

from langchain_community.callbacks.manager import get_openai_callback

with get_openai_callback() as cb:
    result = rag_chain.invoke("سؤال طولانی شما...")
    print(f"Tokens: {cb.total_tokens}")
    print(f"Cost (USD): ${cb.total_cost:.4f}")
    print(f"Cost (Toman): {cb.total_cost * 60000:.0f}")

این را در logger خودت اضافه کن تا هزینهٔ هر فراخوانی را track کنی. در production می‌توانی کاربری که از سقف بودجه گذشت را rate-limit کنی.

جمع‌بندی

LangChain و LangGraph در سال ۱۴۰۵ به ابزارهای استاندارد ساخت اپلیکیشن LLM تبدیل شده‌اند. خوشبختانه به خاطر معماری انعطاف‌پذیر این فریم‌ورک‌ها، اتصال آن‌ها از داخل ایران از طریق پروکسی OpenAI-compatible مثل 1xAi در عمل به یک پارامتر base_url خلاصه می‌شود. هیچ تفاوتی در عملکرد، استریم، function call، یا structured output نیست. اگر تازه شروع کرده‌ای، یک RAG ساده روی مستندات داخلی بساز و ببین چطور کار می‌کند. اگر قبلاً تجربه داری، LangGraph دنیای جدیدی از معماری‌های agent باز می‌کند که با LangChain خالص قابل پیاده‌سازی نبود. برای ساخت workflowهای بدون-کد به جای کد، آموزش n8n را ببین، و برای انتخاب درست مدل، مقایسهٔ GPT-5، GPT-4o و GPT-4.1 راهنمای کاملی است.

ABOUT THE AUTHOR · نویسنده

تیم 1xAi

تیمِ 1xAi پروکسیِ تخصصیِ مدل‌های OpenAI، Claude و Gemini برای کاربرانِ ایرانی را اداره می‌کند — از زیرساختِ شبکه تا صورت‌حسابِ تومانی. هرچه اینجا می‌نویسیم بر اساسِ تجربه‌ٔ روزانه با APIهای OpenAI، Anthropic و Google و نیازهای واقعیِ توسعه‌دهندگانِ داخلِ ایران است.

RELATED · ادامهٔ مطالعه