C++ AI 통합 프로젝트
관련 기초 개념
개요
모델·전처리·비동기·엔진 명령·배포 검사를 연결한다.
먼저 프로파일링·양자화·배포의 핵심 개념을 확인하세요.
핵심 개요
통합 프로젝트에서는 모델 계약·전처리·버퍼 수명·워커·결과 검증·편집 명령·배포를 연결합니다. 추론 결과는 문서 변경의 제안으로 다루고 엔진이 범위·권한·revision·트랜잭션을 검사합니다.
검증은 모델을 대신한 계약 하네스와 실제 ONNX 추론, 실제 Office 엔진 통합을 구분해 수행합니다. 한 단계의 통과를 다른 단계의 완료로 확대하지 않습니다.
필요한 용어
- 어댑터 계약: 모델 결과를 타입 있는 도메인 명령으로 바꾸는 규칙
- Golden case: 기준 입력과 검증된 기대 결과를 저장한 사례
작동 과정
- 작은 기준 모델·입력·기대 출력을 준비합니다.
- 워커의 결과를 검사해 승인 가능한 명령으로 만듭니다.
- 취소·오류·충돌·Undo·배포 환경까지 종단 검사합니다.
풀이 예제
아래 입력과 기록은 직접 만든 교육용 가상 자료입니다.
입력·조건
모델은 셀 분류 결과를 반환했지만 요청 이후 문서가 편집됐습니다.
판단·결과
추론 성공과 별개로 오래된 revision의 편집 계획은 거절·재검증해야 합니다.
이렇게 판단한 이유
모델 입력과 적용 대상의 상태가 달라지면 정확한 과거 결과도 현재 변경으로는 틀릴 수 있습니다.
로컬 실행 예제
Linux C++17·ONNX Runtime 1.31.0 CPU SDK의 include·lib 경로가 필요합니다. ORT_SDK는 받은 공식 SDK의 절대 경로로 설정하세요. linear.onnx는 아래 자료에서 받거나 ONNX 모델과 입출력 계약에서 생성합니다. Windows에는 해당 플랫폼의 SDK·경로 처리가 추가로 필요합니다. 예제의 문서 어댑터는 실제 Office 제품 API가 아닙니다.
export ORT_SDK=/absolute/path/to/onnxruntime-linux-x64-1.31.0
g++ -std=c++17 -pthread onnx_inference.cpp -I "$ORT_SDK/include" -L "$ORT_SDK/lib" -lonnxruntime -Wl,-rpath,"$ORT_SDK/lib" -o onnx_inference
./onnx_inference linear.onnx// Actual ORT CPU inference + a teaching document adapter; not a real Office engine.
#include <onnxruntime_cxx_api.h>
#include <array>
#include <cassert>
#include <cmath>
#include <future>
#include <iostream>
#include <vector>
struct Proposal { int generation, revision; std::vector<float> values; };
struct Document {
std::array<float,3> cells{0,0,0}, before{0,0,0};
int revision=1, undoRevision=0;
bool apply(const Proposal& proposal, int currentGeneration) {
if(proposal.generation!=currentGeneration || proposal.revision!=revision || proposal.values.size()!=3) return false;
std::array<float,3> staged{};
for(int i=0;i<3;++i) {
if(!std::isfinite(proposal.values[i])) return false;
staged[i]=proposal.values[i];
}
before=cells; cells=staged; undoRevision=++revision; return true;
}
bool undo() {
if(undoRevision!=revision) return false;
cells=before; ++revision; undoRevision=0; return true;
}
void remoteEdit() { cells[0]=99; ++revision; undoRevision=0; }
};
int main(int argc, char** argv) {
if(argc!=2) { std::cerr << "usage: onnx_inference linear.onnx\n"; return 2; }
try {
Ort::Env env(ORT_LOGGING_LEVEL_WARNING,"learning");
Ort::SessionOptions options; options.SetIntraOpNumThreads(1);
Ort::Session session(env,argv[1],options);
auto inputType=session.GetInputTypeInfo(0); // Parent owns the borrowed shape view.
auto info=inputType.GetTensorTypeAndShapeInfo();
assert(info.GetElementType()==ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT);
assert((info.GetShape()==std::vector<int64_t>{1,3}));
auto launch = [&](int generation, int revision) {
// Session/env remain alive until all futures finish. Each worker owns its input.
return std::async(std::launch::async,[&session,generation,revision] {
std::array<float,3> input{1,2,3}; std::array<int64_t,2> shape{1,3};
auto memory=Ort::MemoryInfo::CreateCpu(OrtArenaAllocator,OrtMemTypeDefault);
auto tensor=Ort::Value::CreateTensor<float>(memory,input.data(),input.size(),shape.data(),shape.size());
const char* names[]={"x"}; const char* outputs[]={"y"};
auto result=session.Run(Ort::RunOptions{nullptr},names,&tensor,1,outputs,1);
assert(result.size()==1 && result[0].IsTensor());
assert(result[0].GetTensorTypeAndShapeInfo().GetElementCount()==3);
const float* data=result[0].GetTensorData<float>();
return Proposal{generation,revision,std::vector<float>(data,data+3)}; // Copy before result dies.
});
};
Document document;
auto pending=launch(1,document.revision);
const auto proposed=pending.get(); // A CLI test waits; a UI dispatches completion off its event thread.
for(int i=0;i<3;++i) assert(std::fabs(proposed.values[i]-(3+2*i))<1e-6f);
assert(!document.apply(proposed,2)); // Cancelled/replaced generation.
document.remoteEdit();
assert(!document.apply(proposed,1) && document.cells[0]==99); // Stale document.
auto retry=launch(2,document.revision);
assert(document.apply(retry.get(),2));
assert((document.cells==std::array<float,3>{3,5,7}));
assert(document.undo() && document.cells[0]==99); // Restore the state before our own transaction.
assert(!document.undo());
std::cout << "PASS: ORT C++ CPU [3,5,7], async ownership, cancel/stale rejection, commit and Undo\n";
} catch(const Ort::Exception& e) { std::cerr << e.what() << '\n'; return 1; }
}기대 결과: 실제 CPU 출력 [3,5,7]과 비동기 소유·취소·문서 충돌·원자 적용·Undo 검사 PASS.
2026-10-21 로컬 환경에서 실행했습니다. 가상 자료·소형 CPU 예제의 동작 검사이며 실제 업무 모델의 품질·클라우드·GPU·Office 제품 연동 검증은 아닙니다.
실습 자료
흔한 실패와 복구
모의 점수나 하네스 결과를 실제 모델 성능으로 보고하지 않습니다. 사용 모델·장치·검사 단계와 미검증 부분을 적습니다.
확인 문제
모델 추론 성공 뒤에도 필요한 것은?
- 결과 계약·최신 문서·권한·엔진 편집 검증
- 모든 셀에 즉시 적용
- Undo와 저장 검사 생략
풀이 기록 기능을 불러오는 중…
해설 보기
정답: A. 결과 계약·최신 문서·권한·엔진 편집 검증
결과 계약·최신 문서·권한·엔진 편집 검증 모의 점수나 하네스 결과를 실제 모델 성능으로 보고하지 않습니다. 사용 모델·장치·검사 단계와 미검증 부분을 적습니다.
참고 자료
- ONNX Runtime: Ort::Session — 세션 생성·입출력 정보·실행 계약.
- Microsoft: Excel JavaScript application-specific APIs — 셀·범위·배치 실행의 공개 제품 사례.
- Anthropic: Agent evaluations — 과제·시도·실행 결과·평가자 검증.
자료 확인: 2026-10-21. 사례·문항·실습은 자체 제작했습니다. 외부 서비스 호출과 실제 모델 품질 측정은 학습자가 별도 환경에서 수행합니다.
직접 적용하기
교육용 가상 상황
기준 모델은 float32 [1,3] 입력 [1,2,3]을 받아 [3,5,7]을 반환합니다. 문서 초기 셀은 [0,0,0], revision=1입니다. 실행 예제로 요청 취소·원격 편집 후 오래된 제안 거절·재시도·Undo를 확인하고 실제 Office 엔진에 연결할 어댑터의 남은 책임을 적으세요.
모델·전처리·비동기·엔진 명령·배포 검사를 연결한다. 판단 근거와 검증할 결과를 적으세요.
답안 저장 기능을 불러오는 중…
검증 기준과 해설 보기
- 실제 CPU 출력 [3,5,7]과 버퍼·세션 수명을 확인한다
- 취소·문서 변경 후 적용 거절과 재시도·Undo 결과를 확인한다
- 교육용 어댑터와 실제 Office 제품 연동·배포 검사를 구분한다
세대 1 제안을 현재 세대 2로 적용하면 거절됩니다. 원격 편집으로 첫 셀 99/revision 2가 되면 과거 revision 1 제안은 거절됩니다. revision 2에서 다시 추론한 세대 2 제안은 [3,5,7]/revision 3으로 적용되고 Undo는 [99,0,0]/revision 4로 복원합니다. 실제 엔진에서는 권한·셀 범위·수식·트랜잭션·협업 충돌·재접속 검사가 더 필요합니다.
복습하기
- Golden case의 목적은 무엇인가요?
- 어댑터가 하는 일은?
- 통합 완료는 어떻게 보고하나요?
답변 확인 기준
- Golden case의 목적은 무엇인가요?
변경 전후 같은 입력의 결과와 계약을 대조하기 위해서입니다.
- 어댑터가 하는 일은?
모델 결과를 검증된 도메인 명령으로 변환합니다.
- 통합 완료는 어떻게 보고하나요?
모의·실제 추론·실제 제품별 실행 결과와 제한을 나눠 보고합니다.