From 18ec8befb50dfc78c02bd1462046e89560964996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B0=D0=BD=D0=B8=D0=B8=D0=BB=20=D0=92=D0=B8=D0=BA?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=BE=D0=B2?= Date: Thu, 2 Jul 2026 01:43:01 +0000 Subject: [PATCH] =?UTF-8?q?add:=20main.py=20=E2=80=94=20=D1=81=D1=8B=D1=80?= =?UTF-8?q?=D0=BE=D0=B9=20=D1=82=D0=B5=D0=BA=D1=81=D1=82=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B4=D0=B0=D0=BD=D0=B8=D1=8F=20=E2=86=92=20=D0=BF=D0=BB=D0=BE?= =?UTF-8?q?=D1=81=D0=BA=D0=B0=D1=8F=20=D0=BA=D0=B0=D1=80=D1=82=D0=BE=D1=87?= =?UTF-8?q?=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 main.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..a3c2bec --- /dev/null +++ b/main.py @@ -0,0 +1,106 @@ +import os +import asyncio +from typing import List + +from pydantic import BaseModel, Field +from langchain_openai import ChatOpenAI +from langchain_core.prompts import PromptTemplate +from langchain_core.output_parsers import PydanticOutputParser +from langchain_core.messages import HumanMessage +from langchain.tools import tool + +from deepagents import create_deep_agent +from deepagents.backends import FilesystemBackend, LocalShellBackend, CompositeBackend + +# -------------------- Pydantic model -------------------- +class AssignmentCard(BaseModel): + title: str = Field(description="Краткое название задания") + subject: str = Field(description="Тема или предмет задания") + deadline_hint: str = Field(description="Подсказка о сроке сдачи (например, к пятнице, 12.09)") + deliverable_type: str = Field(description="Что нужно сдать: отчёт, код, презентация и т.п.") + grading_hints: List[str] = Field(description="Список упомянутых критериев оценки") + +# -------------------- Structured output parser -------------------- +parser = PydanticOutputParser(pydantic_object=AssignmentCard) + +# -------------------- Prompt template -------------------- +prompt_template = PromptTemplate( + template=( + "Ты получаешь неформальное описание учебного задания и должен вернуть " + "структурированные данные в формате JSON, соответствующем схеме ниже.\n" + "Верни только JSON, без пояснений.\n" + "Описание задания:\n{task_description}\n\n" + "{format_instructions}" + ), + input_variables=["task_description"], + partial_variables={"format_instructions": parser.get_format_instructions()}, +) + +# -------------------- LLM (OpenRouter) -------------------- +llm = ChatOpenAI( + model="openai/gpt-oss-20b:free", + base_url="https://openrouter.ai/api/v1", + api_key=os.getenv("OPENAI_API_KEY"), + temperature=0.0, +) + +# -------------------- Tool that runs the chain -------------------- +@tool +def parse_assignment(task_description: str) -> str: + """ + Parse a free-form assignment description into a structured AssignmentCard. + Returns a JSON string that can be parsed by the Pydantic model. + """ + chain = prompt_template | llm | parser + result = chain.invoke({"task_description": task_description}) + # result is an AssignmentCard instance + return result.model_dump_json(indent=2) + +# -------------------- DeepAgent setup -------------------- +backend = CompositeBackend( + [ + LocalShellBackend(workspace_dir="./workspace"), + FilesystemBackend(), + ] +) + +agent = create_deep_agent( + model=llm, + tools=[parse_assignment], + backend=backend, + system_prompt="You are a helpful assistant that extracts assignment data.", +) + +# -------------------- Main execution -------------------- +async def main(): + # Пример входного текста + user_input = ( + "Сдайте к пятнице мини-отчёт по LangChain: 2 страницы, упор на агентов. " + "Оценка: за полноту и за пример кода." + ) + result = await agent.ainvoke( + {"messages": [HumanMessage(content=user_input)]}, + {"configurable": {"thread_id": "session-1"}}, + ) + # Последнее сообщение агента содержит JSON строку + json_output = result["messages"][-1].content + print("=== Structured JSON ===") + print(json_output) + + # Для наглядности выводим человекочитаемую сводку + try: + import json + + data = json.loads(json_output) + print("\n=== Human-readable summary ===") + print(f"Title: {data.get('title')}") + print(f"Subject: {data.get('subject')}") + print(f"Deadline hint: {data.get('deadline_hint')}") + print(f"Deliverable type: {data.get('deliverable_type')}") + print(f"Grading hints: {', '.join(data.get('grading_hints', []))}") + except Exception as e: + print("Failed to parse JSON:", e) + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file