دستیار آموزشگاه
برای هر دوره یک فضای کاری، تا هنرجوها هر ساعت از روز از درسهای خودشان جواب بگیرند.
هنرجوها دربارهٔ دورهشان — اسلایدها، جزوهها و کلاسهای ضبطشده — داخل اپ خودتان سؤال میپرسند. هر جواب نشان میدهد از کدام فایل درس آمده است.
معماری
برای هر دوره یک فضای کاری. هنرجوی یک دوره هیچوقت از فایلهای دورهٔ دیگر جواب نمیگیرد، چون جستوجو هرگز از مرز فضای کاری رد نمیشود.
- در پیکربندی خودتان، هر دوره را به یک شناسهٔ فضای کاری و هر جلسه را به شناسههای منابعش وصل کنید.
- شناسهٔ هنرجو را بهعنوان
external_user_idبفرستید تا تاریخچهٔ هر هنرجو جدا بماند. - برای جواب فقط از درس همین هفته، شناسههایش را در
resource_idsبفرستید. اگر نفرستید، کل دوره جستوجو میشود.
راهاندازی
برای هر دوره یک فضای کاری بسازید و فایلهای دوره را در آن بارگذاری کنید: PDF، اسلاید بهشکل تصویر و ضبط کلاسها. صبر کنید تا هر فایل آماده شود، بعد هنرجوها دربارهاش بپرسند.
کد
اول دوره پیدا میشود تا دورهٔ ناشناخته زود خطا بدهد، نه اینکه در فایلهای اشتباه بگردد:
const BASE = "https://api.daneshyar.info/api/v1";
const KEY = process.env.DANESHYAR_API_KEY;
/**
* One workspace per course. A student of Biology 101 never gets an answer
* from Chemistry 201's notes, because retrieval cannot cross a workspace.
*/
const COURSES = {
"biology-101": "8f14e45f-ceea-467a-9f4c-1a2b3c4d5e6f",
"chemistry-201": "1d4c7b90-3e58-4a21-bf06-9c2e5d8a7f43",
};
/**
* Keep each lesson's resource ids in your own config. Pass them as
* resource_ids to answer from this week's lesson only.
*/
const LESSONS = {
"biology-101": {
"week-3": ["3c9a1b77-0d24-4e8b-b0f1-7a5e9c2d4b81"],
},
};
/** Called from your own /tutor/ask route, which holds the key. */
export async function askTutor({ studentId, course, lesson, question, sessionId }) {
const workspaceId = COURSES[course];
if (!workspaceId) throw new Error(`Unknown course: ${course}`);
const res = await fetch(`${BASE}/workspaces/${workspaceId}/chat/`, {
method: "POST",
headers: { "X-API-Key": KEY, "Content-Type": "application/json" },
body: JSON.stringify({
// Your student id, so each student keeps their own history.
external_user_id: studentId,
session_id: sessionId,
message: question,
// Leave it out to search the whole course.
resource_ids: LESSONS[course]?.[lesson],
}),
});
if (!res.ok) {
const body = await res.json().catch(() => ({}));
throw new Error(body.message ?? body.detail ?? `HTTP ${res.status}`);
}
const { data } = await res.json();
const reply = data.assistant_message;
return {
sessionId: data.session.id,
answer: reply.content,
// Show the student which lesson file the answer came from.
sources: [
...new Map(
reply.citations.map((c) => [c.resource_id, c.resource_title]),
),
].map(([id, title]) => ({ id, title })),
};
}نتیجه
هر هنرجو دقیقاً از فایلهای دورهٔ خودش جواب میگیرد، با نام درس زیر هر جواب و تاریخچهٔ خودش. اضافه کردن یک دوره یعنی یک فضای کاری و یک خط پیکربندی.