這是一篇為了 04/18 跟 Google Developer Group 合作的 BUILD WITH AI (BWAI) WORKSHOP 的最後一篇文章,畢竟晚上就要工作坊了(投影片可以當場弄,文章可來不及當場寫 XD )。
// Person 定義了 JSON 資料的結構體
type Person struct {
Name string `json:"name"`
Title string `json:"title"`
Address string `json:"address"`
Email string `json:"email"`
Phone string `json:"phone"`
Company string `json:"company"`
}
Add to a list of data in the database. Every time you push a new node onto a list, your database generates a unique key, like messages/users/<unique-user-id>/<username>
const DBCardPath = "namecard"
.....
// Insert the person data into firebase
userPath := fmt.Sprintf("%s/%s", DBCardPath, uID)
_, err = fireDB.NewRef(userPath).Push(ctx, person)
if err != nil {
log.Println("Error inserting data into firebase:", err)
}
// Load all cards from firebase
var People map[string]Person
err = fireDB.NewRef(userPath).Get(ctx, &People)
if err != nil {
fmt.Println("load memory failed, ", err)
}
// Marshall data to JSON
jsonData, err := json.Marshal(People)
if err != nil {
fmt.Println("Error marshalling data to JSON:", err)
}
const ImgagePrompt = `This is a receipt, and you are a secretary.
Please organize the details from the receipt into JSON format for me.
I only need the JSON representation of the receipt data. Eventually,
I will need to input it into a database with the following structure:
Receipt(ReceiptID, PurchaseStore, PurchaseDate, PurchaseAddress, TotalAmount) and
Items(ItemID, ReceiptID, ItemName, ItemPrice).
Data format as follow:
- ReceiptID, using PurchaseDate, but Represent the year, month, day, hour, and minute without any separators.
- ItemID, using ReceiptID and sequel number in that receipt.
Otherwise, if any information is unclear, fill in with "N/A".
`
// Pass the text content to the gemini-pro model for receipt translation.
model = client.GenerativeModel("gemini-pro")
transJson := fmt.Sprintf("%s \n --- \n %s", TranslatePrompt, ret)
res, err := model.GenerateContent(ctx, genai.Text(qry))
if err != nil {
log.Fatal(err)
}
var transRet string
for _, cand := range res.Candidates {
for _, part := range cand.Content.Parts {
transRet = transRet + fmt.Sprintf("%v", part)
log.Println(part)
}
}
相關的應用開發過程中,筆者發現使用 GPT-Vision 可以讓掃描的成果比起 OCR 更容易接受。甚至可以接受更大的 range ,擺放歪了甚至是有被塗鴉過後,還是可以被識別。 而且以往使用 OCR 往往太複雜,需要對其邊界後,準備好相關套版最後才能掃瞄出答案。
在名片掃描過程中,筆者也發現使用英文名片的姓名辨識效果會比較好。可能的問題出在,因為中文名字就是沒有關連的三個文字,而英文名字在許多文章中都有出現過。 這邊建議可以透過簡單的 OCR 套件,將姓名或是公司名稱抓出來,來優化整體的處理效果。
在做 GPT-Vision 開發上,筆者發現 Prompt 的設定跟相關的前處理與後處理其實非常跟你的問題領域有關。如果用名片,就有名片相關的部分。反之,用收據的領域又大大不同。 如果要使用一些瀏覽器介面的時候,常常會有切換的問題。這時候建議直接開發一個 LINE Bot 讓你使用上相當的輕鬆又自在。