DeepSeek - API - chat

Share your advanced PureBasic knowledge/code with the community.
zippo
New User
New User
Posts: 5
Joined: Tue Aug 27, 2024 12:39 pm
Location: Croatia

DeepSeek - API - chat

Post by zippo »

# v:0.3 2024-09-04 # - parsed SQL code
# v:0.2 2024-08-30 #
# v:0.1 2024-08-29 #

This code demonstrates a straightforward way to integrate an AI service into a PureBasic application, offering an alternative to more expensive options while maintaining functionality and ease of use.

This PureBasic application interfaces with the DeepSeek API to send user queries and display the AI-generated responses. It sets up a window with an input field for queries, a button to send requests, and an editor gadget to show the responses. The program constructs a JSON payload with the user's query, sends it asynchronously to the API using HTTP POST, and parses the JSON response to extract and display the content part.
Key Features:
API Interaction: Sends user queries to the DeepSeek API.
JSON Parsing: Extracts the "content" field from the JSON response.
User Interface: Provides a simple GUI for input and areas for displaying the AI response and parsed SQL code. (ask a question that generates SQL code)

read:: https://platform.deepseek.com/api-docs/

If you want to use this code, you need to obtain/purchase an API key. The price starts at around $2, but they are really generous with the tokens!

I left you my API key with $2 credit, so please don't use mine too much; get your own instead!

Code: Select all

;--
; Deepseek - API - chat
; Written by: zippo # v:0.3 2024-09-04 # v:0.2 2024-08-30 # v.0.1 2024-08-29 # 
; Read:: https://platform.deepseek.com/api-docs/
; --

; Setting API key and URL
Global APIKey$ = "sk-f19f96cc03a347898dd969662e2a87a2" ; Replace with your actual API key
Global APIUrl$ = "https://api.deepseek.com/chat/completions"

Enumeration
  #json
EndEnumeration

Procedure.s ExtractContent(jsonResponse$)
  Protected result$ = ""
  
  ; Create a new JSON object for this request
  If CreateJSON(0)
    If ParseJSON(0, jsonResponse$)
      ; Get the root JSON object
      Protected root = JSONValue(0)
      
      ; Access the "choices" array
      Protected choicesArray = GetJSONMember(root, "choices")
      If choicesArray And JSONType(choicesArray) = #PB_JSON_Array
        ; Access the first element in the "choices" array
        Protected firstChoice = GetJSONElement(choicesArray, 0)
        If firstChoice And JSONType(firstChoice) = #PB_JSON_Object
          ; Access the "message" object
          Protected messageObject = GetJSONMember(firstChoice, "message")
          If messageObject And JSONType(messageObject) = #PB_JSON_Object
            ; Access the "content" string
            Protected content = GetJSONMember(messageObject, "content")
            If content And JSONType(content) = #PB_JSON_String
              result$ = GetJSONString(content)
            EndIf
          EndIf
        EndIf
      EndIf
      
    EndIf
    ; Clear and free the JSON object
    FreeJSON(0)
  EndIf
  
  ProcedureReturn result$
EndProcedure

Procedure.s ExtractSQLCode(content$)
  Protected sqlCode$ = ""
  Protected startPos = FindString(content$, "```sql", 1)
  Protected endPos = FindString(content$, "```", startPos + 6)
  
  If startPos > 0 And endPos > 0
    sqlCode$ = Mid(content$, startPos + 6, endPos - startPos - 6)
  EndIf
  
  ProcedureReturn sqlCode$
EndProcedure

; Function for sending HTTP request
Procedure SendRequest(query$)
  Protected json$, HttpRequest, Progress, *Buffer, response$, content$, sqlCode$
  
  json$ = UnescapeString(~"{"+#CRLF$) +
          UnescapeString(~"  \"model\": \"deepseek-chat\","+ #CRLF$) +
          UnescapeString(~"  \"messages\": ["+ #CRLF$) +
          UnescapeString(~"    {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},"+ #CRLF$) +
          UnescapeString(~"    {\"role\": \"user\", \"content\": \"") + EscapeString(query$, #PB_String_EscapeJSON) + UnescapeString(~"\"}" + #CRLF$) +
          UnescapeString(~"  ]," + #CRLF$ ) +
          UnescapeString(~"  \"stream\": false"+#CRLF$ ) +
          "}"

  ; Setting headers using NewMap
  NewMap Header$()
  Header$("Content-Type") = "application/json"
  Header$("Authorization") = "Bearer " + APIKey$
  Header$("User-Agent") = "PureBasic Client"

  ; Sending asynchronous HTTP POST request
  HttpRequest = HTTPRequest(#PB_HTTP_Post, APIUrl$, json$, #PB_HTTP_Asynchronous, Header$())
  
  If HttpRequest
    Debug "Request sent successfully"

    Repeat
      Progress = HTTPProgress(HttpRequest)
      Select Progress
        Case #PB_HTTP_Success
          Debug "Request completed successfully"
          *Buffer = HTTPMemory(HttpRequest)
          If *Buffer
            response$ = PeekS(*Buffer, MemorySize(*Buffer), #PB_UTF8) ;  Getting the entire JSON response
            content$ = ExtractContent(response$)                      ; Extracting only the "content" part
            sqlCode$ = ExtractSQLCode(content$)                       ; Extracting SQL code from content
            Debug "-----------------------------------------------"
            Debug response$
            Debug "-----------------------------------------------"
            Debug content$
            Debug "-----------------------------------------------"
            Debug sqlCode$
            Debug "-----------------------------------------------"
            SetGadgetText(3, content$) ; Displaying content in EditorGadget
            SetGadgetText(4, sqlCode$) ; Displaying SQL code in new EditorGadget
            FreeMemory(*Buffer)
          EndIf
          FinishHTTP(HttpRequest)
          Break

        Case #PB_HTTP_Failed
          Debug "Request failed"
          FinishHTTP(HttpRequest)
          Break

        Case #PB_HTTP_Aborted
          Debug "Request aborted"
          FinishHTTP(HttpRequest)
          Break

        Default
          Debug "Current progress: " + Progress ; It shows the current progress of the download in bytes. (tnx idle! :)
          Delay(100)
      EndSelect
    ForEver
  Else
    Debug "Request creation failed"
  EndIf
EndProcedure

;-- main application window
OpenWindow(0, 100, 100, 600, 500, "DeepSeek API Example")
TextGadget(0, 10, 10, 580, 30, "Enter your query:")
StringGadget(1, 10, 50, 580, 30, "")
ButtonGadget(2, 10, 100, 580, 30, "Send")
TextGadget(6, 10, 133, 580, 30, "AI response:")
EditorGadget(3, 10, 150, 580, 230, #PB_Editor_WordWrap)
TextGadget(5, 10, 383, 580, 30, "SQL code (parse '''SQL '''):")
EditorGadget(4, 10, 400, 580, 80, #PB_Editor_WordWrap) ; New EditorGadget for SQL code

;-- loop for events
Repeat
  Event = WaitWindowEvent()
  Select Event
    Case #PB_Event_Gadget
      If EventGadget() = 2
        query$ = GetGadgetText(1)
        SendRequest(query$)
      EndIf
  EndSelect
Until Event = #PB_Event_CloseWindow
End
Last edited by zippo on Wed Sep 04, 2024 11:51 am, edited 2 times in total.
User avatar
idle
Always Here
Always Here
Posts: 5898
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: DeepSeek - API - chat

Post by idle »

Good example, thanks for sharing.
I asked it to translate one of your code comments and to tell me what language it was.

Prikazuje trenutni napredak preuzimanja u bajtovima

The language of the text you provided is Croatian. Here is the translation To English:

"It shows the current progress of the download in bytes."
zippo
New User
New User
Posts: 5
Joined: Tue Aug 27, 2024 12:39 pm
Location: Croatia

Re: DeepSeek - API - chat

Post by zippo »

idle wrote: Thu Aug 29, 2024 11:55 pm Good example, thanks for sharing.
I asked it to translate one of your code comments and to tell me what language it was.

Prikazuje trenutni napredak preuzimanja u bajtovima

The language of the text you provided is Croatian. Here is the translation To English:

"It shows the current progress of the download in bytes."

You're right, most of the comments are in Croatian. :oops: I've modified and updated the code.
Thank you!
Post Reply