λ€λ₯Έ μΈμ΄λ‘ μ½κΈ°: English, ζ₯ζ¬θͺ
LLM ν¨μ νΈμΆμ νΉνλ κ°μ₯ κ°λ¨ν AI μμ΄μ νΈ λΌμ΄λΈλ¬λ¦¬μμ.
@wrtnlabs/agentλ LLM(λκ·λͺ¨ μΈμ΄ λͺ¨λΈ) ν¨μ νΈμΆμ νΉνλ κ°μ₯ κ°λ¨ν AI μμ΄μ νΈ λΌμ΄λΈλ¬λ¦¬μμ. Swagger/OpenAPI λ¬Έμλ TypeScript ν΄λμ€ νμ
μ ν΅ν΄ νΈμΆν ν¨μλ₯Ό μ 곡νλ©΄ λͺ¨λ κΈ°λ₯μ΄ κ°λ₯ν΄μ Έμ. μνΌ AI μ±λ΄ κ°λ°μ΄λ λ©ν° μμ΄μ νΈ μ€μΌμ€νΈλ μ΄μ
, λͺ¨λ κ²μ ν¨μ νΈμΆμ ν΅ν΄ μ€νν μ μμ΄μ.
μλ₯Ό λ€μ΄, μΌνλͺ° μλ²μ Swagger λ¬Έμλ₯Ό μ 곡νλ©΄ @wrtnlabs/agentλ μνΌ AI μ±λ΄ μ ν리μΌμ΄μ
μ ꡬμ±ν΄μ. μ΄ μ±λ΄ μ ν리μΌμ΄μ
μμ κ³ κ°μ λν ν
μ€νΈλ§μΌλ‘ μ νμ ꡬ맀ν μ μμ΄μ. μλ΄μ΄λ νλΆ νλ‘μΈμ€λ₯Ό μλννκ³ μΆλ€λ©΄ Swagger λ¬Έμλ§ μ λ¬νλ©΄ λΌμ.
λν, LLM ν¨μ νΈμΆ μ λ΅μ λ©ν° μμ΄μ νΈ μ€μΌμ€νΈλ μ΄μ
μ ν¨κ³Όμ μ΄μμ. λ 볡μ‘ν νλ μμν¬λ₯Ό λ°°μ°κ³ νΉμ ν¨λ¬λ€μμ΄λ ν¨ν΄μ λ°λ₯΄λ κ²λ³΄λ€ ν¨μ¬ μ½κ² κ°λ°ν μ μμ΄μ. ν΄λμ€ μ°κ²°λ§ νλ©΄ λκ³ TypeScript ν΄λμ€ νμ
μ μ λ¬νμΈμ. @wrtnlabs/agentκ° ν¨μ νΈμΆμ ν΅ν΄ λ©ν° μμ΄μ νΈ μ€μΌμ€νΈλ μ΄μ
μ μ€μ μ§μ€ννκ³ μ€νν κ±°μμ.
shopping-chat.mp4
μΌν AI μ±λ΄μ μμ° λμμμ΄μμ.
npm install @wrtnlabs/agent @samchon/openapi typia
npx typia setup@wrtnlabs/agentλΏλ§ μλλΌ @samchon/openapiμ typiaλ μ€μΉν΄μΌ ν΄μ.
@samchon/openapiλ Swagger/OpenAPI λ¬Έμλ₯Ό LLM ν¨μ νΈμΆ μ€ν€λ§λ‘ λ³νν μ μλ OpenAPI μ¬μ λΌμ΄λΈλ¬λ¦¬μμ. typiaλ TypeScript ν΄λμ€ νμ
μμ LLM ν¨μ νΈμΆ μ€ν€λ§λ₯Ό ꡬμ±ν μ μλ λ³νκΈ°(μ»΄νμΌλ¬) λΌμ΄λΈλ¬λ¦¬μμ.
μ°Έκ³ λ‘, typiaλ μ»΄νμΌ μμ€μμ TypeScript μμ€ μ½λμ νμ
μ λΆμνλ λ³νκΈ° λΌμ΄λΈλ¬λ¦¬μ΄λ―λ‘ μΆκ° μ€μ λͺ
λ ΉμΈ npx typia setupμ΄ νμν΄μ. νμ€μ΄ μλ TypeScript μ»΄νμΌλ¬(tsc)λ₯Ό μ¬μ©νμ§ μκ±°λ νλ‘ νΈμλ νκ²½μμ μμ΄μ νΈλ₯Ό κ°λ°νλ κ²½μ° @ryoppippi/unplugin-typiaλ μ€μ ν΄μΌ ν΄μ.
import { IHttpLlmApplication } from "@samchon/openapi";
import { WrtnAgent, createHttpApplication } from "@wrtnlabs/agent";
import OpenAI from "openai";
import { IValidation } from "typia";
const main = async (): Promise<void> => {
// SWAGGER λ¬Έμλ₯Ό λ‘λνκ³ LLM μμ© μ€ν€λ§λ‘ λ³ν
const application: IValidation<IHttpLlmApplication<"chatgpt">> =
createHttpApplication({
model: "chatgpt",
document: OpenApi.convert(
await fetch("https://shopping-be.wrtn.ai/editor/swagger.json").then(
(r) => r.json()
)
),
});
if (application.success === false) {
console.error(application.errors);
throw new Error("λμ swagger λ¬Έμμ μ ν μ€λ₯ λ°μ");
}
// μμ΄μ νΈλ₯Ό μ ν리μΌμ΄μ
κ³Ό ν¨κ» μμ±
const agent: WrtnAgent = new WrtnAgent({
provider: {
type: "chatgpt",
model: "gpt-4o-mini",
api: new OpenAI({
apiKey: "YOUR_OPENAI_API_KEY",
}),
},
controllers: [
{
protocol: "http",
name: "shopping",
application: application.data,
connection: {
host: "https://shopping-be.wrtn.ai",
},
},
],
config: {
locale: "en-US",
},
});
// μ΄λ²€νΈ 리μ€λ μΆκ°
agent.on("select", async (<
8000
/span>select) => {
console.log("μ νλ ν¨μ", select.operation.function.name);
});
agent.on("execute", async (execute) => {
consoe.log("μ€νλ ν¨μ", {
function: execute.operation.function.name,
arguments: execute.arguments,
value: execute.value,
});
});
// AI μ±λ΄κ³Ό λν
await agent.conversate("What you can do?");
};
main().catch(console.error);Swagger λ¬Έμλ₯Ό λ‘λνκ³ κ·Έκ²μ @wrtnlabs/agentμ μ λ¬νκΈ°λ§ νλ©΄ λΌμ.
κ·Έλ¬λ©΄ λ°±μλ μλ²μμ λνκ° μμλκ³ , λ°±μλ μλ²μ API ν¨μκ° μλμΌλ‘ νΈμΆλ κ±°μμ. AI μ±λ΄μ λν ν μ€νΈλ₯Ό λΆμνκ³ LLM ν¨μ νΈμΆ κΈ°λ₯μ ν΅ν΄ μ μ ν API ν¨μλ₯Ό μ€νν΄μ.
μ΄μ λΆν° λͺ¨λ λ°±μλ κ°λ°μλ λμμ AI κ°λ°μμμ.
import { WrtnAgent } from "@wrtnlabs/agent";
import typia, { tags } from "typia";
import OpenAI from "openai";
class BbsArticleService {
/**
* μλ‘μ΄ κΈ°μ¬λ₯Ό μμ±νμΈμ.
*
* μ κΈ°μ¬λ₯Ό μμ±νκ³ DBμ 보κ΄νμΈμ.
*
* @param props μμ± ν¨μμ μμ±
* @returns μλ‘ μμ±λ κΈ°μ¬
*/
public async create(props: {
/**
* μμ±ν κΈ°μ¬μ μ 보
*/
input: IBbsArticle.ICreate;
}): Promise<IBbsArticle>;
/**
* κΈ°μ¬λ₯Ό μ
λ°μ΄νΈνμΈμ.
*
* κΈ°μ¬λ₯Ό μλ‘μ΄ μ½ν
μΈ λ‘ μ
λ°μ΄νΈνμΈμ.
*
* @param props μ
λ°μ΄νΈ ν¨μμ μμ±
* @param input μ
λ°μ΄νΈν μλ‘μ΄ μ½ν
μΈ
*/
public async update(props: {
/**
* νκ² κΈ°μ¬μ {@link IBbsArticle.id}.
*/
id: string & tags.Format<"uuid">;
/**
* μ
λ°μ΄νΈν μλ‘μ΄ μ½ν
μΈ .
*/
input: IBbsArticle.IUpdate;
}): Promise<void>;
}
const main = async (): Promise<void> => {
const api: OpenAI = new OpenAI({
apiKey: "YOUR_OPENAI_API_KEY",
});
const agent: WrtnAgent = new WrtnAgent({
provider: {
type: "chatgpt",
model: "gpt-4o-mini",
api: new OpenAI({
apiKey: "YOUR_OPENAI_API_KEY",
}),
},
controllers: [
{
protocol: "class",
name: "vectorStore",
application: typia.llm.applicationOfValidate<
BbsArticleService,
"chatgpt"
>(),
execute: new BbsArticleService(),
},
],
});
await agent.conversate("I wanna write an article.");
};
main().catch(console.error);TypeScript ν΄λμ€μλ λνν μ μμ΄μ.
TypeScript νμ
μ @wrtnlabs/agentμ μ λ¬νκ³ λνλ₯Ό μμν΄ λ³΄μΈμ. κ·Έλ¬λ©΄ @wrtnlabs/agentκ° LLM ν¨μ νΈμΆ κΈ°λ₯μ ν΅ν΄ λν ν
μ€νΈλ₯Ό λΆμνμ¬ μ μ ν ν΄λμ€ ν¨μλ₯Ό νΈμΆν κ±°μμ.
μ΄μ λΆν° μ¬λ¬λΆμ΄ κ°λ°ν λͺ¨λ TypeScript ν΄λμ€κ° AI μ±λ΄μ΄ λ μ μμ΄μ.
import { WrtnAgent } from "@wrtnlabs/agent";
import typia from "typia";
import OpenAI from "openai";
class OpenAIVectorStoreAgent {
/**
* RAGλ‘ λ²‘ν° DBλ₯Ό κ²μνμΈμ.
*
* @param props λ²‘ν° DB κ²μ μμ±
*/
public async query(props: {
/**
* μ‘°νν ν€μλ.
*
* μ‘°ννκ³ μΆμ λͺ¨λ ν€μλλ₯Ό λ£μΌμΈμ. κ·Έλ¬λ ν΅μ¬λ§ ν¬ν¨μν€κ³
* λΆλͺ
νν λ΄μ©μ μ μΈνμ¬ μ νν κ²°κ³Όλ₯Ό μ»μΌμΈμ.
*/
keywords: string;
}): Promise<IVectorStoreQueryResult>;
}
const main = async (): Promise<void> => {
const api: OpenAI = new OpenAI({
apiKey: "YOUR_OPENAI_API_KEY",
});
const agent: WrtnAgent = new WrtnAgent({
provider: {
type: "chatgpt",
model: "gpt-4o-mini",
api: new OpenAI({
apiKey: "YOUR_OPENAI_API_KEY",
}),
},
controllers: [
{
protocol: "class",
name: "vectorStore",
application: typia.llm.applicationOfValidate<
OpenAIVectorStoreAgent,
"chatgpt"
>(),
execute: new OpenAIVectorStoreAgent({
api,
id: "YOUR_OPENAI_VECTOR_STORE_ID",
}),
},
],
});
await agent.conversate("I wanna research economic articles");
};
main().catch(console.error);@wrtnlabs/agentμμλ λ©ν° μμ΄μ νΈ μ€μΌμ€νΈλ μ΄μ
μ μμ£Ό μ½κ² ꡬνν μ μμ΄μ.
Vector Storeμ κ°μ μμ΄μ νΈ κΈ°λ₯μ κ°μΆ TypeScript ν΄λμ€λ₯Ό κ°λ°νκ³ , μμ κ°μ΄ TypeScript ν΄λμ€ νμ
μ @wrtnlabs/agentμ μ λ¬νμΈμ. @wrtnlabs/agentλ TypeScript ν΄λμ€λ‘ LLM ν¨μ νΈμΆ μ λ΅μ ν΅ν΄ λ©ν° μμ΄μ νΈ μ€μΌμ€νΈλ μ΄μ
μ μ€μ μ§μ€ννκ³ μ€νν κ±°μμ.
sequenceDiagram
actor User
actor Agent
participant Selector
participant Executor
participant Describer
activate User
User-->>Agent: λν:<br/>μ¬μ©μ λ°μΈ
activate Agent
Agent->>Selector: λν ν
μ€νΈ μ λ¬
activate Selector
deactivate User
Note over Selector: ν보 κΈ°λ₯ μ ν λλ μ κ±°
alt ν보 μμ
Selector->>Agent: μΌλ° ChatGPT λν
deactivate Selector
Agent->>User: λν:<br/>μμ΄μ νΈ λ°μΈ
activate User
deactivate User
end
deactivate Agent
loop ν보 κΈ°λ₯ μ‘΄μ¬
activate Agent
Agent->>Executor: λν ν
μ€νΈ μ λ¬
activate Executor
alt 컨ν
μ€νΈ μΆ©λΆ
Note over Executor: μΆ©μ‘±λ ν¨μ νΈμΆ
Executor->>Describer: ν¨μ νΈμΆ κΈ°λ‘
deactivate Executor
activate Describer
Describer->>Agent: ν¨μ νΈμΆ μ€λͺ
deactivate Describer
Agent->>User: λν:<br/>μμ΄μ νΈ μ€λͺ
activate User
deactivate User
else 컨ν
μ€νΈ λΆμΆ©λΆ
break
Executor->>Agent: μΆκ° μ 보 μμ²
end
Agent->>User: λν:<br/>μμ΄μ νΈ μμ²
activate User
deactivate User
end
deactivate Agent
end
μ¬μ©μκ° λ°μΈμ νλ©΄, @wrtnlabs/agentλ λν ν
μ€νΈλ₯Ό selector μμ΄μ νΈμ μ λ¬νκ³ , selector μμ΄μ νΈκ° 컨ν
μ€νΈμμ ν보 ν¨μλ₯Ό μ°Ύκ±°λ μ·¨μνλλ‘ ν©λλ€. selector μμ΄μ νΈκ° νΈμΆν ν보 ν¨μλ₯Ό μ°Ύμ μ μκ³ μ΄μ μ μ νλ ν보 ν¨μλ μλ€λ©΄, selector μμ΄μ νΈλ μΌλ° ChatGPTμ²λΌ μλν©λλ€.
κ·Έλ¦¬κ³ @wrtnlabs/agentλ ν보 ν¨μκ° λΉμ΄μ§ λκΉμ§ λ°λ³΅λ¬Έμ λ€μ΄κ°λλ€. μ΄ λ°λ³΅λ¬Έμμ executor μμ΄μ νΈλ μ¬μ©μμ λν ν
μ€νΈλ₯Ό λΆμν΄ LLM ν¨μ νΈμΆμ μλν©λλ€. λ§μ½ 컨ν
μ€νΈκ° ν보 ν¨μμ μΈμλ₯Ό ꡬμ±νκΈ°μ μΆ©λΆνλ€λ©΄, executor μμ΄μ νΈλ μ€μ λ‘ λμ ν¨μλ₯Ό νΈμΆνκ³ , describer μμ΄μ νΈκ° ν¨μ νΈμΆ κ²°κ³Όλ₯Ό μ€λͺ
νλλ‘ ν©λλ€. λ°λλ‘ μ»¨ν
μ€νΈκ° μΆ©λΆνμ§ μλ€λ©΄ executor μμ΄μ νΈλ μ¬μ©μμκ² μΆκ° μ 보λ₯Ό μμ²ν©λλ€.
μ΄λ¬ν LLM(λκ·λͺ¨ μΈμ΄ λͺ¨λΈ) ν¨μ νΈμΆ μ λ΅μμ selector, executor, describerλ₯Ό λΆλ¦¬νλ κ²μ΄ @wrtnlabs/agentμ ν΅μ¬ λ‘μ§μ
λλ€.
import { FunctionCall } from "pseudo";
import { ILlmFunctionOfValidate, IValidation } from "typia";
export const correctFunctionCall = (p: {
call: FunctionCall;
functions: Array<ILlmFunctionOfValidate<"chatgpt">>;
retry: (reason: string, errors?: IValidation.IError[]) => Promise<unknown>;
}): Promise<unknown> => {
// FIND FUNCTION
const func: ILlmFunctionOfValidate<"chatgpt"> | undefined =
p.functions.find(f => f.name === p.call.name);
if (func === undefined) {
// never happened in my experience
return p.retry(
"Unable to find the matched function name. Try it again.",
);
}
// VALIDATE
const result: IValidation<unknown> = func.validate(p.call.arguments);
if (result.success === false) {
// 1st trial: 50% (gpt-4o-mini in shopping mall chatbot)
// 2nd trial with validation feedback: 99%
// 3nd trial with validation feedback again: never have failed
return p.retry(
"Type errors are detected. Correct it through validation errors",
{
errors: result.errors,
},
);
}
return result.data;
}LLM ν¨μ νΈμΆμ΄ μλ²½ν κΉμ?
μ λ΅μ μλμμ. OpenAIμ κ°μ LLM(λκ·λͺ¨ μΈμ΄ λͺ¨λΈ) μ 곡μλ λμ ν¨μ νΈμΆμ μΈμλ₯Ό ꡬμ±ν λ λ§μ νμ
μ€λ₯λ₯Ό μ μ§λ¬μ. LLM ν¨μ νΈμΆ μ€ν€λ§κ° Array<string> νμ
μΌλ‘ μ μλμ΄ μμ΄λ, LLMμ μ’
μ’
λ¨μΌ string κ°λ§μΌλ‘ ꡬμ±μ νκ³€ ν΄μ.
λ°λΌμ LLM ν¨μ νΈμΆ μμ΄μ νΈλ₯Ό κ°λ°ν λ, κ²μ¦ νΌλλ°± νλ‘μΈμ€κ° νμμ μΌλ‘ μꡬλ©λλ€. LLMμ΄ μΈμ ꡬμ±μ ν λ νμ μ€λ₯λ₯Ό λ²νλ©΄, μμ΄μ νΈλ κ°μ₯ μμΈν κ²μ¦ μ€λ₯λ₯Ό νΌλλ°± νκ³ , LLMμ΄ κ²μ¦ μ€λ₯λ₯Ό μ°Έκ³ νμ¬ ν¨μ νΈμΆμ μ¬μλ νλλ‘ ν΄μΌ λΌμ.
κ²μ¦ νΌλλ°± κ΄λ ¨νμ¬, @wrtnlabs/agentλ typia.validate<T>()μ typia.llm.applicationOfValidate<Class, Model>() κΈ°λ₯μ νμ©ν΄μ. μ΄λ€μ μ»΄νμΌ μμ€μμ TypeScript μμ€ μ½λλ₯Ό λΆμνμ¬ κ²μ¦ λ
Όλ¦¬λ₯Ό ꡬμΆνκΈ° λλ¬Έμ λ€λ₯Έ μ΄λ κ²μ¦κΈ° 보λ€λ μμΈνκ³ μ νν΄μ. κ·Έλ¬λ―λ‘ κ°μ₯ μ΄μμ μΈ LLM ν¨μ νΈμΆμ μ€ννκ² λμμ΄μ. μ κ²½νμμ OpenAIμ gpt-4o-mini λͺ¨λΈμ μ¬μ©ν λ, μ²μ μλμ μ½ 50% μ λλ μ ν¨νμ§ μμ ν¨μ νΈμΆ μΈμλ₯Ό ꡬμ±νλ κ²½ν₯μ 보μμ΄μ. νμ§λ§ typiaμ κ²μ¦ νΌλλ°±μ ν΅ν΄ μμ νκ² λλ©΄ μ±κ³΅λ₯ μ΄ 99%λ‘ κΈκ²©ν μμΉν΄μ. κ·Έλ¦¬κ³ κ²μ¦ νΌλλ°±μ λ λ² μλνλ©΄ μ€ν¨ν μ μ΄ μμ΄μ.
| μ»΄ν¬λνΈ | typia |
TypeBox |
ajv |
io-ts |
zod |
C.V. |
|---|---|---|---|---|---|---|
| μ¬μ©νκΈ° μ¬μ | β | β | β | β | β | β |
| κ°μ²΄ (κ°λ¨) | β | β | β | β | β | β |
| κ°μ²΄ (κ³μΈ΅) | β | β | β | β | β | β |
| κ°μ²΄ (μ¬κ·) | β | β | β | β | β | β |
| κ°μ²΄ (μ λμ¨, μμ) | β | β | β | β | β | β |
| κ°μ²΄ (μ λμ¨, λͺ μ) | β | β | β | β | β | β |
| κ°μ²΄ (μΆκ° νκ·Έ) | β | β | β | β | β | β |
| κ°μ²΄ (ν νλ¦Ώ 리ν°λ΄ νμ ) | β | β | β | β | β | β |
| κ°μ²΄ (λμ μμ±) | β | β | β | β | β | β |
| λ°°μ΄ (νν νν) | β | β | β | β | β | β |
| λ°°μ΄ (κ³μΈ΅) | β | β | β | β | β | β |
| λ°°μ΄ (μ¬κ·) | β | β | β | β | β | β |
| λ°°μ΄ (μ¬κ·, μ λμ¨) | β | β | β | β | β | β |
| λ°°μ΄ (R+U, μμ) | β | β | β | β | β | β |
| λ°°μ΄ (μ€λ³΅) | β | β | β | β | β | β |
| λ°°μ΄ (μ€λ³΅, μ λμ¨) | β | β | β | β | β | β |
| κΆκ·Ήμ μ λμ¨ νμ | β | β | β | β | β | β |
C.V.λclass-validatorλ₯Ό μλ―Έν΄μ
flowchart
subgraph "OpenAPI λͺ
μΈ"
v20("Swagger v2.0") --μ
κ·Έλ μ΄λ--> emended[["OpenAPI v3.1 (μμ λ¨)"]]
v30("OpenAPI v3.0") --μ
κ·Έλ μ΄λ--> emended
v31("OpenAPI v3.1") --μμ --> emended
end
subgraph "OpenAPI λ³νκΈ°"
emended --μ κ·ν--> migration[["λ§μ΄κ·Έλ μ΄μ
μ€ν€λ§"]]
migration --"μΈκ³΅μ§λ₯"--> lfc{{"LLM ν¨μ νΈμΆ"}}
lfc --"OpenAI"--> chatgpt("ChatGPT")
lfc --"Anthropic"--> claude("Claude")
lfc --"Google"--> gemini("Gemini")
lfc --"Meta"--> llama("Llama")
end
@wrtnlabs/agentλ Swagger/OpenAPI λ¬Έμμ TypeScript ν΄λμ€ νμ
μμ LLM ν¨μ νΈμΆ μ€ν€λ§λ₯Ό μ»μ΄μ. TypeScript ν΄λμ€ νμ
μ typia.llm.applicationOfValidate<Class, Model>() ν¨μλ₯Ό ν΅ν΄ LLM ν¨μ νΈμΆ μ€ν€λ§λ‘ λ³νλ μ μμ΄μ. κ·Έλ λ€λ©΄ OpenAPI λ¬Έμλ μ΄λ»κ² LLM ν¨μ νΈμΆ μ€ν€λ§κ° λ μ μμκΉμ?
λΉλ°μ μμ λ€μ΄μ΄κ·Έλ¨μ μμ΅λλ€.
OpenAPI λͺ
μΈμλ μλ‘ λ€λ₯Έ μ μλ₯Ό κ°μ§ μΈ κ°μ§ λ²μ μ΄ μμ΄μ. μ¬μ§μ΄ κ°μ λ²μ μμλ λ무 λ§μ λͺ¨νΈνκ³ μ€λ³΅λ ννμ΄ ν¬ν¨λμ΄ μμ΄μ. μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ @samchon/openapiλ λͺ¨λ OpenAPI λ¬Έμλ₯Ό v3.1μ μμ λ λͺ
μΈλ‘ λ³ννκ³ μμ΄μ. @samchon/openapiμ μμ λ v3.1 λͺ
μΈλ λͺ¨νΈνκ³ μ€λ³΅λ λͺ¨λ ννμ μ κ±°νμ¬ λͺ
νν¨μ μΆκ΅¬ν΄μ.
μμ λ v3.1 OpenAPI λ¬Έμλ₯Ό ν΅ν΄, @samchon/openapiλ μ΄λ₯Ό ν¨μ ꡬ쑰μ κ°κΉμ΄ λ§μ΄κ·Έλ μ΄μ
μ€ν€λ§λ‘ λ³νν©λλ€. κ·Έλ¦¬κ³ λ§μ§λ§ λ¨κ³μμλ λ§μ΄κ·Έλ μ΄μ
μ€ν€λ§κ° νΉμ LLM μ 곡μμ ν¨μ νΈμΆ μ€ν€λ§λ‘ λ³νλ©λλ€. LLM ν¨μ νΈμΆ μ€ν€λ§λ μ΄λ κ² κ΅¬μ±λ©λλ€.
μ μ§μ λ³ννμ§ μκ³ , μ€κ° λ¨κ³λ₯Ό κ±°μΉλμ?
κ° λ²μ μ OpenAPI λͺ μΈμμ νΉμ LLMμ ν¨μ νΈμΆ μ€ν€λ§λ‘ μ§μ λ³ννλ€λ©΄ λ°μΉ΄λ₯΄νΈ κ³±μ μν΄ ν¨μ¬ λ λ§μ λ³νκΈ°λ₯Ό λ§λ€μ΄μΌ ν΄μ. νμ¬ λͺ¨λΈμμλ λ³νκΈ°μ μκ° 12 = 3 x 4 κ° λ©λλ€.
νμ§λ§ μ€κ° μ€ν€λ§λ₯Ό μ μνλ©΄ λ³νκΈ°μ μ«μλ λ§μ μ°μ°μΌλ‘ μ€μ΄λ€μ΄μ. νμ¬ λͺ¨λΈμμλ 7 = 3 + 4 λ§ μμΌλ©΄ λκ³ , μ΄κ²μ΄ μ€κ° λͺ μΈλ₯Ό μ μν μ΄μ μ λλ€. μ΄ λ°©λ²μ κ²½μ μ μ΄μμ.
μ¬κΈ° README λ¬Έμμμ @wrtnlabs/agentλ μ£Όμ κ°λ
κ³Ό μμΉμ μκ°νκ³ μΌλΆ μμλ₯Ό 보μ¬μ£Όκ³ μμ΄μ.
νμ§λ§, AI μ±λ΄ κ°λ°μ λ΄ μ»€λ¨Έλ€μκ²λ μ΄ λ΄μ©λ§μΌλ‘λ μΆ©λΆνμ§ μμμ. κ°μ΄λ λ¬Έμμ μμ νλ‘μ νΈκ° κ΅μ‘μ μν΄ λ§μ΄ νμν΄μ. μ°λ¦¬λ LLM ν¨μ νΈμΆμ μ΅μ νλ μ¬λ°λ₯Έ μ μλ₯Ό μμ±νλ λ°©λ²μ λ°±μλ κ°λ°μμκ² μλ΄νκ³ , λ©ν° μμ΄μ νΈ μ€μΌμ€νΈλ μ΄μ ꡬνμ μμ΄μ μ΅μμ λ°©λ²μ μκ°ν νμκ° μμ΄μ.
2025λ 3μ 31μΌκΉμ§ μ΄λ¬ν μμΈν κ°μ΄λ λ¬Έμλ₯Ό μμ±ν μμ μ΄κ³ , μμ±λκΈ°κΉμ§ κ³μν΄μ λ¬Έμλ₯Ό λ°νν μμ μ΄μμ.
https://nestia.io/chat/playground
μ λ μμ μ Swagger AI μ±λ΄ νλ μ΄κ·ΈλΌμ΄λ μΉμ¬μ΄νΈλ₯Ό κ°λ°ν μ μ΄ μμ΄μ.
κ·Έλ¬λ TypeScript ν΄λμ€ νμ
μμ ν¨μ μ€ν€λ§λ₯Ό μ»λ λ€λ₯Έ λΆλΆμ μμ§ μ€λΉλμ§ μμμ΄μ. TypeScript μ»΄νμΌλ¬(tsc)λ₯Ό λ΄μ₯νμ¬ TypeScript ν΄λμ€ νμ
κΈ°λ°μ νλ μ΄κ·ΈλΌμ΄λ μΉμ¬μ΄νΈλ₯Ό λ§λ€ κ±°μμ.
μλ‘μ΄ νλ μ΄κ·ΈλΌμ΄λ μΉμ¬μ΄νΈλ 2025λ 3μ 15μΌκΉμ§ 곡κ°λ μμ μ΄μμ.
μ΄κΈ°μλ POC(κ°λ
μ¦λͺ
) κ°λ°μ μ§μ€νκΈ° λλ¬Έμ, @wrtnlabs/agentλ₯Ό ꡬμ±νλ λ΄λΆ μμ΄μ νΈλ€μ΄ μμ§ λΉμ© μ΅μ νλμ§ μμμ΄μ. νΉν, selector μμ΄μ νΈλ LLM ν ν°μ κ³Όλνκ² λ°λ³΅ μλΉνκ³ μμ΄μ. selector μμ΄μ νΈλ₯Ό RAG(κ²μ μ¦κ° μμ±μ ν΅ν μ΅μ ν) κΈ°μ μ ν΅ν΄ μ΅μ νν μμ μ΄μμ.
λν, @wrtnlabs/agentμ μ°κ²°ν μ μλ λ€μμ μ μ©ν μ λμ¨ μμ΄μ νΈλ₯Ό μ§μν μμ μ΄μμ. κ·Έ μ€ νλμΈ @wrtnlabs/hiveλ selector μμ΄μ νΈλ₯Ό μ΅μ ννμ¬ LLM λΉμ©μ ν¬κ² μ€μ¬μ€λλ€. κ·Έ μΈμλ OpenAI λ²‘ν° μ€ν μ΄ νΈλ€λ¬μ Postgres κΈ°λ° RAG μμ§λ μ 곡λ μμ μ΄μμ.
μ΄λ¬ν @wrtnlabs/agentκ° μ 곡νλ μ λμ¨ μμ΄μ νΈλ₯Ό ν΅ν΄ TypeScript ν΄λμ€ ν¨μ νΈμΆμ ν΅ν λ©ν° μμ΄μ νΈ μ€μΌμ€νΈλ μ΄μ
ꡬν λ°©λ²μ λ°°μΈ μ μκ³ , @wrtnlabs/agentκ° λ©ν° μμ΄μ νΈ μμ€ν
μνΈμμ©μ μΌλ§λ μ½κ² λ§λλμ§ μ΄ν΄ν μ μμ΄μ.
import {
IWrtnAgentEvent,
IWrtnAgentHeader,
IWrtnAgentListener,
IWrtnAgentService
} from "@wrtnlabs/agent";
import { Driver, WebSocketConnector } from "tgrid";
const main = async (): Promise<void> => {
const connector: WebSocketConnector<
IWrtnAgentHeader,
IWrtnAgentListener,
IWrtnAgentService
> = new WebSocketConnector(
{
locale: "en-US",
} satisfies IWrtnAgentHeader,
{
// EVENT LISTENERS
conversate: async (event: IWrtnAgentEvent.IConversate) => {},
select: async (event: IWrtnAgentEvent.ISelect) => {},
execute: async (event: IWrtnAgentEvent.IExecute) => {},
describe: async (event: IWrtnAgentEvent.IDescribe) => {},
} satisfies IWrtnAgentService,
);
await connector.connect("http://localhost:3000/chat");
// CALL SERVER'S FUNCTION
const service: Driver<IWrtnAgentService> = connector.getDriver();
await service.conversate("Hello, what you can do?");
};
main().catch(console.error);@wrtnlabs/agentλ RPC(μ격 νλ‘μμ νΈμΆ) ν¨λ¬λ€μμ μΉμμΌ λͺ¨λμ μ 곡ν μμ μ΄μμ.
μ΄ μΉμμΌ λͺ¨λμ μμ΄μ νΈ λ°±μλ μλ²μ AI μ±λ΄ νλ‘ νΈμλ μ ν리μΌμ΄μ μ μ½κ² ν΅ν©ν μ μκ² λμμ€ κ±°μμ.
μ΄ κΈ°λ₯μ 2025λ 2μ 28μΌκΉμ§ μ§μν μμ μ΄μμ.
flowchart
Agent["<code>@wrtnlabs/agent</code>"]
OpenAI("<b><u>OpenAI</u></b>")
Claude
Llama
Gemini
Agent==supports==>OpenAI
Agent-.not yet.->Claude
Agent-.not yet.->Llama
Agent-.not yet.->Gemini
νμ¬ @wrtnlabs/agentλ OpenAIλ§ μ§μν΄μ.
μ΄κΈ°μλ POC(κ°λ
μ¦λͺ
) λ° λ°λͺ¨ λ¨κ³μ΄κΈ° λλ¬Έμ OpenAIλ§ μ§μνμ§λ§, AI μΈμμμ κ°μ₯ μ λͺ
ν λͺ¨λΈμΈ OpenAI μΈμλ, @wrtnlabs/agentλ λ λμ μ¬μ©μμΈ΅μ μν΄ λ§μ λͺ¨λΈμ μ§μν΄μΌ ν΄μ.
2025λ 4μ 30μΌκΉμ§ λ λ§μ λͺ¨λΈμ μ§μν μμ μ΄μμ.