MCPcopy Create free account
hub / github.com/bigdata-ustc/Agent4Edu / LLMClient

Class LLMClient

Code/llm_client.py:8–84  ·  view source on GitHub ↗

Small LLM wrapper used by the Action module. The default provider is ``mock`` so the repository can be smoke-tested without network access or API keys. Set ``AGENT4EDU_LLM_PROVIDER=openai`` for real simulation.

Source from the content-addressed store, hash-verified

6
7
8class LLMClient:
9 """Small LLM wrapper used by the Action module.
10
11 The default provider is ``mock`` so the repository can be smoke-tested without
12 network access or API keys. Set ``AGENT4EDU_LLM_PROVIDER=openai`` for real
13 simulation.
14 """
15
16 def __init__(self, provider: str | None = None, model: str | None = None):
17 self.provider = provider or SIM_PARAMS.get("llm_provider", "mock")
18 self.model = model or self._default_model()
19 self.client: Any | None = None
20 if self.provider == "openai":
21 from openai import OpenAI
22
23 kwargs: dict[str, Any] = {"api_key": OPENAI_API_KEY}
24 if OPENAI_BASE_URL:
25 kwargs["base_url"] = OPENAI_BASE_URL
26 self.client = OpenAI(**kwargs)
27
28 def _default_model(self) -> str:
29 mtype = SIM_PARAMS.get("gpt_type", 0)
30 if mtype == 0:
31 return os.getenv("AGENT4EDU_OPENAI_MODEL", "gpt-3.5-turbo-1106")
32 if mtype == 1:
33 return os.getenv("AGENT4EDU_OPENAI_MODEL", "gpt-4-1106-preview")
34 return os.getenv("AGENT4EDU_OPENAI_MODEL", "gpt-4o-mini")
35
36 def call(self, messages: list[dict[str, str]]) -> str:
37 if self.provider == "mock":
38 return self._mock_call(messages)
39 if self.provider != "openai":
40 raise ValueError(f"Unsupported LLM provider: {self.provider}")
41 if not OPENAI_API_KEY:
42 raise RuntimeError("OPENAI_API_KEY is empty. Set it or use AGENT4EDU_LLM_PROVIDER=mock.")
43 assert self.client is not None
44 resp = self.client.chat.completions.create(
45 model=self.model,
46 messages=messages,
47 temperature=0,
48 timeout=120,
49 max_tokens=2048,
50 )
51 return resp.choices[0].message.content or ""
52
53 def _mock_call(self, messages: list[dict[str, str]]) -> str:
54 user = "\n".join(m.get("content", "") for m in messages if m.get("role") == "user")
55 if "reflection" in user.lower() and "learning status" in user.lower():
56 return (
57 "The recent practice suggests a stable learning state. The learner should keep reinforcing "
58 "concepts that appeared in recent mistakes and connect them with previously practiced concepts."
59 )
60 concept = self._extract_first_option(user) or "unknown concept"
61 return (
62 "Task1: Yes\n"
63 f"Task2: {concept}\n"
64 "Task3: I will use the relevant concept and previous practice experience to identify the key condition, "
65 "then derive the answer step by step.\n"

Callers 2

__init__Method · 0.90
mainFunction · 0.90

Calls

no outgoing calls

Tested by

no test coverage detected