fix: build_chain() + inference BroJS вместо localhost
This commit is contained in:
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user