fix: build_chain() + inference BroJS вместо localhost

This commit is contained in:
2026-05-27 08:08:01 +00:00
parent be20311547
commit f3c7258e9c
+50 -24
View File
@@ -8,16 +8,16 @@ from dotenv import load_dotenv
from langchain_core.output_parsers import PydanticOutputParser from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import PromptTemplate from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field, SecretStr from pydantic import BaseModel, Field
load_dotenv() load_dotenv()
# Модель: LM Studio локально или любой OpenAI-совместимый API через .env BROJS_INFERENCE_URL = "https://platform.brojs.ru/jrnl-bh/api/inference/v1"
llm = ChatOpenAI( DEFAULT_MODEL = "openai/gpt-oss-20b:free"
model=os.getenv("OPENAI_MODEL", "local-model"),
base_url=os.getenv("OPENAI_BASE_URL", "http://localhost:1234/v1"), DEFAULT_INPUT = (
api_key=SecretStr(os.getenv("OPENAI_API_KEY", "fake")), "Сдайте к пятнице мини-отчёт по LangChain: 2 страницы, упор на агентов. "
temperature=0.0, "Оценка: за полноту и за пример кода."
) )
@@ -37,25 +37,51 @@ class AssignmentCard(BaseModel):
) )
parser = PydanticOutputParser(pydantic_object=AssignmentCard) def _api_key() -> str:
return (
os.getenv("OPENAI_API_KEY")
or os.getenv("JOURNAL_MCP_PAT")
or os.getenv("JOURNAL_TOKEN")
or ""
)
prompt = PromptTemplate(
template=(
"Ты модуль разбора учебных заданий. Из одной формулировки преподавателя "
"извлеки поля карточки. Не задавай уточняющих вопросов — только структурированный ответ.\n\n"
"Формулировка задания:\n{assignment_text}\n\n"
"{format_instructions}"
),
input_variables=["assignment_text"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
chain = prompt | llm | parser def _base_url() -> str:
if os.getenv("OPENAI_BASE_URL"):
return os.environ["OPENAI_BASE_URL"]
if os.getenv("OPENAI_API_KEY"):
return os.getenv("OPENROUTER_BASE_URL", "https://openrouter.ai/api/v1")
return BROJS_INFERENCE_URL
DEFAULT_INPUT = (
"Сдайте к пятнице мини-отчёт по LangChain: 2 страницы, упор на агентов. " def _model() -> str:
"Оценка: за полноту и за пример кода." return os.getenv("OPENAI_MODEL") or os.getenv("OPENROUTER_MODEL") or DEFAULT_MODEL
)
def build_chain():
"""Цепочка prompt | llm | parser — точка входа для автопроверки."""
parser = PydanticOutputParser(pydantic_object=AssignmentCard)
prompt = PromptTemplate(
template=(
"Ты модуль разбора учебных заданий. Из одной формулировки преподавателя "
"извлеки поля карточки. Не задавай уточняющих вопросов — только структурированный ответ.\n\n"
"Формулировка задания:\n{assignment_text}\n\n"
"{format_instructions}"
),
input_variables=["assignment_text"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
llm = ChatOpenAI(
model=_model(),
base_url=_base_url(),
api_key=_api_key(),
temperature=0.0,
)
return prompt | llm | parser
def parse_assignment_text(assignment_text: str) -> AssignmentCard:
return build_chain().invoke({"assignment_text": assignment_text})
def human_summary(card: AssignmentCard) -> str: def human_summary(card: AssignmentCard) -> str:
@@ -72,7 +98,7 @@ def human_summary(card: AssignmentCard) -> str:
def main() -> None: def main() -> None:
assignment_text = " ".join(sys.argv[1:]).strip() or DEFAULT_INPUT assignment_text = " ".join(sys.argv[1:]).strip() or DEFAULT_INPUT
card: AssignmentCard = chain.invoke({"assignment_text": assignment_text}) card = parse_assignment_text(assignment_text)
print("=== Валидированный объект (model_dump) ===") print("=== Валидированный объект (model_dump) ===")
dumped = card.model_dump() dumped = card.model_dump()