તમે ગોવા માટે પ્રવાસનું આયોજન કરવા માંગો છો. તમારી પાસે પાંચ દિવસ છે, 25,000 રૂપિયાનું બજેટ છે, અને બીચ (beaches) તથા સીફૂડ (seafood) માટે સ્પષ્ટ પસંદગી છે. સામાન્ય રીતે, આનો અર્થ એ થાય કે દસ બ્રાઉઝર ટેબ ખોલવા, જૂની થઈ ગયેલી ફોરમ પોસ્ટ્સ વાંચવી અને મેન્યુઅલી એક ઇટિનરરી (itinerary) તૈયાર કરવી. તેના બદલે, કલ્પના કરો કે તમે ફક્ત એક સિંગલ POST request મોકલો છો અને બદલામાં ભોજનના સૂચનો, પ્રવૃત્તિઓની યાદી અને ચોક્કસ બજેટ વિભાજન સાથેનું એક સ્ટ્રક્ચર્ડ ડે-બાય-ડે પ્લાન મેળવો છો. આ પ્રોજેક્ટ તે જ પ્રદાન કરે છે.
અમે Spring Boot અને Azure OpenAI નો ઉપયોગ કરીને એક REST API બનાવીશું. આ API ડેસ્ટિનેશન (destination), બજેટ, સમયગાળો અને રુચિઓ સ્વીકારે છે. તે ક્લીન JSON રિટર્ન કરે છે જેને ફ્રન્ટએન્ડ અથવા મોબાઈલ એપ તરત જ રેન્ડર કરી શકે છે. કોઈ સ્ક્રેપિંગ નહીં. કોઈ હાર્ડકોડેડ ઇટિનરરી નહીં. ફક્ત એક AI મોડલ જેને ટ્રાવેલ પ્લાનર તરીકે કામ કરવા માટે પ્રોમ્પ્ટ કરવામાં આવ્યું છે.
API શું રિટર્ન કરે છે
રિસ્પોન્સ એ Markdown ટેક્સ્ટનો બ્લોક નથી જેને તમારે regex દ્વારા અલગ કરવો પડે. તે દૈનિક પ્રવૃત્તિઓ, ભોજનની ભલામણો અને બજેટના વિભાજન ધરાવતો એક સ્ટ્રક્ચર્ડ JSON ઓબ્જેક્ટ છે. ગોવા પ્રવાસ માટે, તમને એવો વિભાગ મળી શકે છે જે બીચ શેક (beach shack) પર નાસ્તા માટે 500 રૂપિયા, સવારે Palolem માં સમય વિતાવવો અને સાંજે કોઈ ચોક્કસ વિસ્તારમાં સીફૂડ ડિનર માટે બજેટ ફાળવે છે. દરેક દિવસમાં સમયના સ્લોટ્સ, અંદાજિત ખર્ચ અને "beach" અથવા "food" જેવા ટેગ્સ હોય છે. આ સ્ટ્રક્ચર મહત્વનું છે કારણ કે આધુનિક ટ્રાવેલ એપ્સ પેરાગ્રાફ પાર્સ (parse) કરવા નથી માંગતી. તેઓ એવા ઓબ્જેક્ટ્સ ઈચ્છે છે જેને તેઓ RecyclerViews અથવા React components માં મેપ કરી શકે.
ટેક સ્ટેક અને તે શા માટે યોગ્ય છે
આ પ્રોજેક્ટ Spring AI સાથે Spring Boot 3.5 નો ઉપયોગ કરે છે. Spring AI એ સૌથી મહત્વનો ભાગ છે. તે એક યુનિફાઇડ ChatModel એબ્સ્ટ્રેક્શન પૂરું પાડે છે જેથી તમારે Azure OpenAI સામે રૉ (raw) HTTP ક્લાયન્ટ્સ લખવા ન પડે. તમે સર્વિસ કોડને બદલવાને બદલે માત્ર ડિપેન્ડન્સીઝ અને પ્રોપર્ટીઝ બદલો છો.
તમારે તમારી બિલ્ડ ફાઇલમાં ચાર ડિપેન્ડન્સીઝની જરૂર પડશે:
- REST લેયર માટે
spring-boot-starter-web. - Spring AI ના ઇન્ટરફેસ દ્વારા LLM સાથે કનેક્ટ કરવા માટે
spring-ai-starter-model-azure-openai. - ઓટોમેટિક Swagger ડોક્યુમેન્ટેશન માટે
springdoc-openapi. - તમારા રિક્વેસ્ટ અને રિસ્પોન્સ POJOs માંથી બોઈલરપ્લેટ (boilerplate) ઘટાડવા માટે
Lombok.
Spring AI તમારા બિઝનેસ લોજિક અને LLM પ્રોવાઈડર વચ્ચે કામ કરે છે. આ પોઝિશનિંગ જાણીજોઈને કરવામાં આવ્યું છે. તે તમારા @Service ક્લાસને ક્લીન અને પ્રોવાઈડર-એગ્નોસ્ટિક (provider-agnostic) રાખે છે.
PromptTemplates સાથે Prompt Engineering
Java સ્ટ્રિંગ્સની અંદર પ્રોમ્પ્ટ્સ હાર્ડકોડ કરવા એ મેન્ટેનેબલ સોફ્ટવેર બનાવવાનો ઝડપી રસ્તો છે. જો પ્રોડક્ટ ટીમ નક્કી કરે કે AI ને વધુ કેઝ્યુઅલ રીતે વાત કરવી જોઈએ અથવા ચોક્કસ મર્યાદાથી ઉપરના બજેટ અંદાજોનો ઇનકાર કરવો જોઈએ, તો તમારે તમારી સર્વિસને ફરીથી કમ્પાઈલ કરવાની જરૂર ન પડવી જોઈએ.
Spring AI PromptTemplate પૂરું પાડે છે. તમે પ્રોમ્પ્ટનું માળખું (skeleton) રિસોર્સ ફાઇલમાં અથવા સમર્પિત ટેમ્પલેટ સ્ટ્રિંગમાં સ્ટોર કરો છો, જેમાં {destination}, {budget}, {days}, અને {interests} જેવા વેરિએબલ્સ માટે પ્લેસહોલ્ડર્સ રાખવામાં આવે છે. રનટાઇમ પર, સર્વિસ એક Prompt ઓબ્જેક્ટ બનાવે છે અને યુઝરની વેલ્યુઝ ઇન્જેક્ટ કરે છે.
સિસ્ટમ મેસેજને યુઝર મેસેજથી અલગ રાખો. પર્સના (persona) વ્યાખ્યાયિત કરવા માટે સિસ્ટમ મેસેજનો ઉપયોગ કરો. ઉદાહરણ તરીકે, તમે મોડલને કહો છો કે તે ભારતીય ડેસ્ટિનેશનમાં નિષ્ણાત, બજેટ પ્રત્યે સભાન અને માર્કડાઉન ફેન્સ વગર ફક્ત JSON રિટર્ન કરવા માટે કડક ટ્રાવેલ પ્લાનર છે. ચોક્કસ ટ્રિપની વિગતો પાસ કરવા માટે યુઝર મેસેજનો ઉપયોગ કરો. આ વિભાજન તમને મદદ કરે છે જ્યારે તમે પાછળથી API કોન્ટ્રાક્ટ બદલ્યા વગર પર્સનાનું A/B ટેસ્ટ કરવા માંગતા હોવ.
સર્વિસ લેયર: Azure OpenAI સાથે વાતચીત
@Service ક્લાસનું એક જ કામ છે. તે પ્રોમ્પ્ટ બનાવે છે, મોડલને કોલ કરે છે, રિસ્પોન્સ ક્લીન કરે છે અને રિઝલ્ટ પાર્સ કરે છે.
Spring AI ના ChatClient અથવા ChatModel ને ઇન્જેક્ટ કરો. આવતી રિક્વેસ્ટ વેલ્યુઝ સાથે PromptTemplate ને રેન્ડર કરો, પછી ચેટ મેથડને કોલ કરો. રિસ્પોન્સ String તરીકે આવે છે. અહીં જ ઘણા ટ્યુટોરિયલ્સ અટકી જાય છે અને અસલી પ્રોડક્શન કોડ શરૂ થાય છે.
LLMs ક્યારેક નમ્ર પ્રસ્તાવના (preambles) ઉમેરે છે. તમને એવો રિસ્પોન્સ મળી શકે છે જે "Here is your itinerary" થી શરૂ થાય અને પછી ટ્રિપલ બેકટિક્સમાં લપેટાયેલું JSON આપે. જો તમે તેને સીધું Jackson સાથે ડીસિરિયલાઇઝ (deserialize) કરવાનો પ્રયાસ કરશો, તો તમારી એપ ક્રેશ થઈ જશે. એક નાનું હેલ્પર મેથડ ઉમેરો જે રૉ સ્ટ્રિંગને સ્કેન કરે, પ્રથમ ઓપનિંગ બ્રેસ { અને છેલ્લો ક્લોઝિંગ બ્રેસ } શોધી કાઢે, અને ફક્ત JSON પેલોડને એક્સટ્રેક્ટ કરે. પછી એક્સટ્રેક્ટ કરેલા બ્લોકને વેલિડેટ કરો. કંટ્રોલરને ઓબ્જેક્ટ રિટર્ન કરતા પહેલા તપાસો કે જરૂરી ફિલ્ડ્સ અસ્તિત્વમાં છે અને ન્યુમેરિક વેલ્યુઝ યોગ્ય છે.
આ ડિફેન્સિવ પાર્સિંગ (defensive parsing) વૈકલ્પિક નથી. તે ડેમો અને વિશ્વસનીય API વચ્ચેની સીમા છે.
પરિપક્વ સિસ્ટમની જેમ ભૂલોનું સંચાલન કરવું
એક્સટર્નલ API નિષ્ફળ જાય છે. Azure OpenAI રેટ લિમિટ એરર્સ, ઓથેન્ટિકેશન નિષ્ફળતા અથવા ટ્રાન્ઝિયન્ટ 500 એરર્સ રિટર્ન કરશે. જો તમે આ ભૂલોને સ્ટેક ટ્રેસ (stack traces) તરીકે યુઝર સુધી પહોંચવા દેશો, તો તમે તમારી વિશ્વસનીયતા ગુમાવશો.
@RestControllerAdvice નો ઉપયોગ કરીને વૈશ્વિક સ્તરે (globally) એક્સેપ્શન્સને ઇન્ટરસેપ્ટ કરો. Spring AI એક્સેપ્શન્સ, HttpClientErrorException, અને સામાન્ય RuntimeException ને સુસંગત એરર રિસ્પોન્સ સાથે મેપ કરો. એક સ્પષ્ટ મેસેજ, રેટ લિમિટ માટે 429 જેવો HTTP સ્ટેટસ, અને ક્લાયન્ટને ફરીથી પ્રયાસ કરવા અથવા સમસ્યા લોગ કરવા માટે પૂરતી વિગતો સાથે JSON બોડી રિટર્ન કરો. વપરાશકર્તાએ "Service temporarily busy. Please retry in 30 seconds," જેવું કંઈક જોવું જોઈએ, Java ક્લાસના નામોથી ભરેલી સ્ક્રીન નહીં.
ક્યારેય સિક્રેટ્સ હાર્ડકોડ ન કરો
તમારી Azure OpenAI API કી Git માં ચેક-ઇન કરેલી application.properties ફાઇલમાં ન હોવી જોઈએ. તેને એક્સટર્નલાઇઝ (Externalize) કરો. તમારી Spring કોન્ફિગરેશનમાં સંદર્ભિત એન્વાયરમેન્ટ વેરિયેબલ્સનો ઉપયોગ કરો, જેમ કે ${AZURE_OPENAI_KEY} અને ${AZURE_OPENAI_ENDPOINT}. ડેવલપમેન્ટ માટે લોકલ .env ફાઇલ રાખો, તેને .gitignore માં ઉમેરો, અને Spring Boot ના રિલેક્સ્ડ બાઇન્ડિંગ (relaxed binding) દ્વારા તેને લોડ કરો. જો કી લીક થાય, તો તમારે આર્ટિફેક્ટ ફરીથી બનાવવાને બદલે ફક્ત એક જ જગ્યાએ તેને બદલી (rotate) શકાય છે.
Swagger દ્વારા ટેસ્ટિંગ
springdoc-openapi ડિપેન્ડન્સી રનટાઇમ પર Swagger UI એન્ડપોઇન્ટ એક્સપોઝ કરે છે. એકવાર તમારું એપ્લિકેશન શરૂ થઈ જાય પછી, બ્રાઉઝરમાં /swagger-ui.html ખોલો. તમે Goa નું ઉદાહરણ સીધું જ ભરી શકો છો: ડેસ્ટિનેશન તરીકે "Goa," બજેટ તરીકે 25000, દિવસો તરીકે 5, અને રસ (interests) તરીકે "beaches, food." એક્ઝિક્યુટ પર ક્લિક કરો અને JSON ઇટિનરરી (itinerary) દેખાતી જુઓ. આ તમને પ્રોમ્પ્ટ ફેરફારોને વેલિડેટ કરવા, સિરિયલાઇઝેશન (serialization) ચકાસવા અને યુનિટ ટેસ્ટ લખતા પહેલા ફ્રન્ટએન્ડ ડેવલપર્સ સાથે લાઈવ પ્લેગ્રાઉન્ડ શેર કરવામાં મદદ કરે છે.
કોડ ફરીથી લખ્યા વિના પ્રોવાઇડર્સ બદલવા
સ્ટાર્ટઅપ્સ પ્રોવાઇડર્સ બદલતા રહે છે. કદાચ Azure ક્રેડિટ્સ સમાપ્ત થઈ જાય, અથવા ખર્ચ ઘટાડવા માટે તમે લોકલ Ollama ઇન્સ્ટન્સ સામે ઇન્ફરન્સ (inference) ચલાવવા માંગતા હોવ. Spring AI ChatModel ઇન્ટરફેસને એબ્સ્ટ્રેક્ટ (abstract) કરે છે, તેથી આ બદલાવ ખૂબ જ સરળ છે. Maven ડિપેન્ડન્સીને spring-ai-starter-model-azure-openai થી બદલીને બીજા સ્ટાર્ટરમાં કરો, તમારી પ્રોપર્ટીઝ ફાઇલમાં નવો એન્ડપોઇન્ટ અને કી અપડેટ કરો, અને તમારી સર્વિસ ક્લાસને અડક્યા વગર રહેવા દો. તમારી મોબાઇલ એપ દ્વારા જોવામાં આવતો API કોન્ટ્રાક્ટ સમાન જ રહેશે.
આ પોર્ટેબિલિટી (portability) આ આર્કિટેક્ચરને વાસ્તવિક પ્રોડક્ટ્સ માટે ખાસ ઉપયોગી બનાવે છે. તમે Azure સાથે લગ્ન નથી કરી રહ્યા. તમે તેનો ઉપયોગ એક ક્લીન Spring પાઇપલાઇનમાં જોડાયેલા એક એન્જિન તરીકે કરી રહ્યા છો.
મુખ્ય સારાંશ
AI મોડલ એ તમારી એપ્લિકેશન નથી. તે એક એક્સટર્નલ સર્વિસ છે જે અનિશ્ચિત ટેક્સ્ટ રિટર્ન કરે છે. તેને તે જ કડકતા સાથે લો જે રીતે તમે પેમેન્ટ ગેટવે અથવા થર્ડ-પાર્ટી વેધર API ને આપશો. તમારા ક્રેડેન્શિયલ્સને એક્સટર્નલાઇઝ કરો. દરેક રિસ્પોન્સને વેલિડેટ કરો. પાર્સિંગ (parsing) કરતા પહેલા પેલોડને ક્લીન કરો. એરર્સને ગ્લોબલી હેન્ડલ કરો જેથી તમારા વપરાશકર્તાઓ ક્યારેય સ્ટેક ટ્રેસ (stack trace) ન જુએ.
25,000 રૂપિયાના બજેટ પર Goa ઇટિનરરી બનાવવાનું સર્જનાત્મક કામ AI ને કરવા દો. તમે પ્લમ્બિંગ (પ્લમ્બિંગ/બેકએન્ડ લોજિક) સંભાળો. જ્યારે આ બંને અલગ રહે છે, ત્યારે તમને એવું સિસ્ટમ મળે છે જે ખરેખર લોન્ચ કરી શકાય તેવું હોય છે.
આ લેખને પ્રેરણા આપનાર મૂળ વોકથ્રુ (walkthrough) અહીં અહીં મળી શકે છે.
Spring AI અને સમાન પ્રોજેક્ટ્સ વિશે ચર્ચા કરવામાં રસ છે? GyaanSetu લર્નિંગ કોમ્યુનિટી માં જોડાઓ.
